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

我检查了engine用于表格及其InnoDB. 我的问题是...

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

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

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

1 回答 1

4

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

14.6.4.4。外键约束

当您使用 ALTER TABLE 向表添加外键约束时,请记住首先创建所需的索引。

并且:

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

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

要回答您的具体问题:

1)它不会限制您,因为您尚未创建所需的索引。如他们的文档中所述,算法使用与约束对应的索引。

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

3)不,这不是坏习惯。你只需要明确你的意图。例如,您想在ALTERing 表后检查参照完整性吗?这是一个可能有用的问题:Force InnoDB to recheck foreign keys on a table/tables?

于 2013-02-05T17:35:02.283 回答