外键约束允许删除父项

时间:2013-02-05 16:26:50

标签: mysql

我对外键限制有疑问。所以我为测试目的制作了两个这样的简单表格。

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。我的问题是......

  1. 为什么它不限制我删除父母中有多个依赖子记录的记录?默认情况下,它应该限制我吗?

  2. 如果我在添加外键约束之前在外键字段上创建索引,则其按预期工作。我是否每次都需要创建这样的索引?

  3. 在创建表后添加任何类型的约束是不好的做法?

1 个答案:

答案 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?

相关问题