Lon*_*olf 85 mysql innodb foreign-key mysql-5.5
我在 MySQL 数据库中有两个表 - parent, child. 我正在尝试根据父表向我的子表添加外键引用。有没有之间的任何显著差异ON UPDATE CASCADE和ON DELETE CASCADE
我的父表
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
Run Code Online (Sandbox Code Playgroud)
我的问题是:以下 sql 查询有什么区别。
ON DELETE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
Run Code Online (Sandbox Code Playgroud)ON UPDATE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE
) ENGINE=INNODB;
Run Code Online (Sandbox Code Playgroud)ON UPDATE CASCADE ON DELETE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=INNODB;
Run Code Online (Sandbox Code Playgroud)查询中是否有任何错误?这些查询 (1,2 & 3) 是什么意思?他们一样吗???
Vér*_*ace 117
关于这个主题的一个很好的线索可以在这里和这里找到。MySQL 的权威指南当然是文档,可在此处找到。
在 SQL 2003 标准中,有 5 种不同的引用操作:
要回答这个问题:
级联
ON DELETE CASCADE意味着如果父记录被删除,所有子记录也将被删除。在我看来,这不是一个好主意。您应该跟踪数据库中曾经存在的所有数据,尽管这可以使用TRIGGERs来完成。(但是,请参阅下面评论中的警告)。
ON UPDATE CASCADE意味着如果父主键发生变化,子值也会发生变化以反映这一点。在我看来,这不是一个好主意。如果您有PRIMARY KEY规律地(甚至根本没有!)更改s,那么您的设计就有问题。再看评论。
ON UPDATE CASCADE ON DELETE CASCADE意味着如果您UPDATE 或 DELETE父级,更改将级联到子级。这相当于ANDing 前两个语句的结果。
严格
RESTRICT意味着任何删除和/或更新父项的尝试都将失败并抛出错误。这是未明确指定引用操作时的默认行为。
对于未指定的
ON DELETE或ON UPDATE,默认操作始终为 RESTRICT`。
没有行动
NO ACTION: 从手册。来自标准 SQL 的关键字。在 MySQL 中,相当于RESTRICT. 如果引用的表中存在相关的外键值,MySQL Server 将拒绝对父表的删除或更新操作。有些数据库系统有延迟检查,并且NO ACTION是延迟检查。在 MySQL 中,会立即检查外键约束,因此NO ACTION与RESTRICT.置空
SET NULL- 再次来自手册。从父表中删除或更新行,并将子表中的外键列设置为NULL。恕我直言,这不是最好的想法,主要是因为没有“时间旅行”的方法 - 即回顾子表并将记录与NULLs 与相关的父记录相关联-CASCADE或者使用TRIGGERs 填充日志表以进行跟踪更改(但是,请参阅评论)。默认设置
SET DEFAULT. SQL 标准的另一个(可能非常有用)部分是 MySQL 没有费心实现的!允许开发人员指定一个值,用于在 UPDATE 或 DELETE 中设置外键列。InnoDB 和 NDB 将拒绝带有SET DEFAULT子句的表定义。如上所述,您应该花一些时间查看文档,这里。
这两个是分别在父表上的引用记录更改其 id 和删除时要执行的操作。
如果执行:
UPDATE parent SET id = -1 WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)
而至少有一个记录上child有parent_id = 1,1)将失败; 在情况 2) 和 3) 中,所有 parent_id = 1 的记录都更新为 parent_id = -1。
如果执行:
DELETE FROM parent WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)
而至少有一个记录上child有parent_id = 1,2)将失败; 在情况 1) 和 3) 中,parent_id = 1删除所有记录。
3) 语法正确。
完整的文档可以在手册中找到。
小智 7
我没有足够的声誉来评论以前的答案。所以我想我会详细说明一下。
1) ON DELETE CASCADE 表示如果父记录被删除,那么所有引用的子记录也被删除。ON UPDATE 默认为 RESTRICT,这意味着父记录上的 UPDATE 将失败。
2) ON DELETE 操作默认为 RESTRICT,这意味着对父记录的 DELETE 将失败。ON UPDATE CASCADE 将在更新父记录时更新所有引用子记录。
3) 请参阅上面 1) 和 2) 中的 CASCADE 操作。
关于使用父记录 ID 作为外键(在子表中)——经验表明 a) 如果 ID 是自动生成的序列号,那么不要将它们用作外键。改用其他一些唯一的父键。b) 如果 ID 是 GUID,那么可以将它们用作外键。当您导出和导入记录或将记录复制到另一个数据库时,您将看到此建议的智慧。数据迁移过程中自动生成的序列号作为外键引用时,处理起来太麻烦了。