2013-02-05 55 views
2

我对外键约束有疑问。所以我为了测试目的制作了两个简单的表格。外键约束允许父键被删除

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); 

我检查用于表和它的InnoDBengine。我的问题是...

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

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

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

默认是'RESTRICT',是的。你可以用'SHOW CREATE TABLE child'来检查;'FK是否已经被实际定义(正确)? –

+0

是的,它是.. ** KEY'parent_fk'('parent_id'), CONSTRAINT'parent_fk' FOREIGN KEY('parent_id')REFERENCES'parent'('id')** –

回答

4

当使用ALTER TABLE添加新的外键约束时,MySQL需要字段索引。该约束将根据父表中的索引进行检查,因此如果没有索引,则不会进行检查。

14.6.4.4. FOREIGN KEY Constraints

当您添加一个外键约束使用ALTER TABLE表,记得先创建所需的索引。

而且,也:

SQL标准的背离:如果在具有相同引用键值父表几行,InnoDB的外键的检查行为,如果对方父行具有相同的键值不存在。例如,如果你定义了一个RESTRICT类型约束,并且有一个包含多个父行的子行,InnoDB不允许删除任何这些父行。

InnoDB根据与外键约束对应的索引中的记录,通过深度优先算法执行级联操作。

为了回答您的具体问题:

1)它不限制你,因为你还没有创建所需的索引。正如他们的文档中所述,算法使用与约束相对应的索引。

2)参见#1。是的,除非FK在将行添加到父表之前就位。

3)不,这是不错的做法。你只需要明确你的意图。例如,你想在表格后检查参照完整性吗?这里有一个潜在的有用的问题:Force InnoDB to recheck foreign keys on a table/tables?

+0

非常感谢!这是我得到的最好的解释:) –