MySQL 主键与外键总结
定义
MySQL 原生支持外键(即允许跨表交叉引用相关数据)和外键约束(用于保持数据一致性!)。
外键关系涉及包含初值的父表,以及引用父表值的子表。而外键约束就定义在子表之上。
A foreign key relationship involves a parent table that holds the initial column values, and a child table with column values that reference the parent column values. A foreign key constraint is defined on the child table.
语法
在 CREATE TABLE
或 ALTER TABLE
语句中定义外键约束的基本语法如下:
1 | [CONSTRAINT [fk_symbol]] FOREIGN KEY |
删除外键约束:
1 | ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol; |
例子
1 | # 创建父表 |
可视化界面如下:
注意:
创建外键约束时,如果主外键之间的数据类型不一致(例如长度、无符号),会报错:
1215 - Cannot add the foreign key constraint
。创建外键约束后,MySQL 会为子表自动创建普通索引
fk_parent_id
,以提升join
查询性能。创建外键不一定只能引用父表的主键,也能引用普通列。如果引用普通列,MySQL 则会在父表和子表同时为该列创建普通索引。如果删除该索引会报错:
1553 - Cannot drop index '...': needed in a foreign key constraint
。reference_option
的几种情况总结如下:操作父表:
RESTRICT
在UPDATE
或者DELETE
父表记录时,对子表进行一致性检查。CASCADE
在UPDATE
或者DELETE
父表记录时,对子表进行级联操作。SET NULL
在UPDATE
或者DELETE
父表记录时,对子表进行 SET NULL 操作。
RESTRICT
(NO ACTION
)CASCADE
SET NULL
INSERT
正常插入 正常插入 正常插入 UPDATE
更新父表值,会报错 1451 - Cannot delete or update a parent row: a foreign key constraint fails
更新父表值,子表值级联更新 更新父表值,子表值 SET NULL DELETE
删除父表行,会报错 1451 - Cannot delete or update a parent row: a foreign key constraint fails
删除父表行,子表行级联删除 删除父表行,子表值 SET NULL 操作子表:
INSERT
、UPDATE
触发一致性检查。
RESTRICT
(NO ACTION
)CASCADE
SET NULL
INSERT
无论哪个 option,插入子表行为父表不存在的值,都会报错 1452 - Cannot add or update a child row: a foreign key constraint fails
UPDATE
同上 DELETE
无论哪个 option,删除子表行都 ok
总结
参考
https://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html