我对外键限制有疑问。所以我为测试目的制作了两个这样的简单表格。
mysql> EXPLAIN parent;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
+-------+---------+------+-----+---------+----------------+
1 row in set (0.01 sec)
mysql> EXPLAIN child;
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| parent_id | int(11) | NO | MUL | NULL | |
+-----------+---------+------+-----+---------+----------------+
现在我没有在创建表时指定外键约束。我后来加了它。
ALTER TABLE child
ADD CONSTRAINT parent_fk FOREIGN KEY(parent_id) REFERENCES parent(id);
我检查了用于表格的engine
及其InnoDB
。我的问题是......
为什么它不限制我删除父母中有多个依赖子记录的记录?默认情况下,它应该限制我吗?
如果我在添加外键约束之前在外键字段上创建索引,则其按预期工作。我是否每次都需要创建这样的索引?
答案 0 :(得分:4)
当使用ALTER TABLE
添加新的外键约束时,MySQL需要字段上的索引。根据父表中的索引检查约束,因此如果没有索引,则不进行检查。
14.6.4.4. FOREIGN KEY Constraints
使用ALTER TABLE向表中添加外键约束时,请记住首先创建所需的索引。
而且,还有:
与SQL标准的偏差:如果父表中有多行具有相同的引用键值,则InnoDB将执行外键检查,就好像其他具有相同键值的父行不存在一样。例如,如果您已定义RESTRICT类型约束,并且存在具有多个父行的子行,则InnoDB不允许删除任何这些父行。
InnoDB基于对应于外键约束的索引中的记录,通过深度优先算法执行级联操作。
回答您的具体问题:
1)它没有限制你,因为你没有创建所需的索引。如他们的文档中所述,算法使用与约束相对应的索引。
2)见#1。是的,除非在将行添加到父表之前FK已就位。
3)不,这不是一种不好的做法。你只需要明确你的意图。例如,您想在ALTER
表后检查参照完整性吗?这是一个可能有用的问题:Force InnoDB to recheck foreign keys on a table/tables?