1.7. 主键和外键
1.7.1. 主键
主键就是能唯一标识表中每条记录的字段,不能有null值,主键可以包含一个字段或者多个字段,
主键要短,可唯一标识记录,且永不改变。一般类型设为 INT(最大可表示2亿,一般足够了,要根据具体的需求决定),设为主键后自动变为不可为空,另外还要设定 AI(Auto Incremental)自动递增,这样会方便许多,不需要担心主键唯一性的问题。
如何产生主键值:
在业务中一般不会用业务字段作为主键,要使用单独的字段作为主键,主要为了保密业务数据,也方便业务字段的修改,生成唯一主键值可采用以下几种方法:
- 主键字段设置为自增
- 使用UUID()函数,会产生一个长度为36个字符的字符串且永不重复,适合在集群环境下,一个表被分在多个服务器上也不会有重复主键。
- 使用 UUID_SHORT() 函数,产生一个64位的无符号整数且全局唯一。
主键和唯一索引:
主键和唯一索引都要求值是唯一的,但它们之间存在一些不同:
- 一个表中只能定义一个主键,但是能定义多个唯一索引。
- 主键中的值不能为 NULL,而索引中的值可以为 NULL。
1.7.2. 外键
什么是外键:
外键用来引用其他表,通过子表的一个或多个字段对应父表的主键或唯一键值,将子表和父表建立关联关系。
外键约束
外键约束能够保证数据的完整和正确。例如,一个国家已经有了城市,就不能轻易的从 country 表删除国家,否则就会造成这个城市数据的不完整。也不能为一个城市设定一个不存在的 country_id,否则这个城市数据就是错误的。
查看一下 city 表定义的外键约束:
sql">SHOW CREATE TABLE city\G
sql">*************************** 1. row ***************************Table: city
Create Table: CREATE TABLE `city` (`city_id` smallint unsigned NOT NULL AUTO_INCREMENT,`city` varchar(50) NOT NULL,`country_id` smallint unsigned NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`city_id`),KEY `idx_fk_country_id` (`country_id`),CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`)REFERENCES `country` (`country_id`)ON DELETE RESTRICTON UPDATE CASCADE) ENGINE=InnoDB AUTO_INCREMENT=601 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
注意其中的部分:
sql">CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`)REFERENCES `country` (`country_id`)ON DELETE RESTRICTON UPDATE CASCADE
这里定义了一个外键:
- 位于 CONSTRAINT 关键字之后的 fk_city_country 是外键的名字。它是可选的。
- 位于 FOREIGN KEY 关键字之后的是作为外键的字段名。
- 位于 REFERENCES 关键字之后的是被引用的表和字段。
- ON DELETE 和 ON UPDATE 指定了删除或更新父表中的数据时要采取的约束策略。可以使用以下 3 个策略中的一个:
-
- CASCADE:如果被引用的表中的一行被删除或更新,该表中匹配行的值会自动删除或更新。
- SET NULL:如果被引用的表中的一行被删除或更新,该表中匹配行的值设置为 NULL。
- RESTRICT: 如果被引用的表中的一行在该表中有匹配的行,试图删除或更新被引用的表中行时会引发 MySQL 错误。这是默认的策略。
通常,外键所属的表被称作子表,被外键引用的表被称作父表。