mysql - 如何应用约束和使用 NO Action 规则意味着不采取任何行动
问题描述
我试图澄清外键约束的正确使用,并在'ON DELETE''NO ACTION'时保持空白。我将保持通用性,因为iis非常简单,无需深入研究有限的细节。
我有一个包含 5 个子表的父表 - 所有表中都有现有数据(它不是新的数据库构建)。我想在逻辑上进行设置以适应我的客户需求和我所期望的!因此,所有父表与子表之间存在一对多的关系:可以有零个或多个记录与父表主键记录相关。永远不会有与父记录无关的子记录(我已经检查过以确保是这样)。
由于现在可能(并且可能存在)任何子表中没有子记录的父记录,因此设置父子约束失败,好吧,我明白为什么,没问题。因此,病态地设置了儿童对父母的约束:
- 如果子记录 (Fk) 已更新,则将父记录 (PK) 更新为相同。
- 如果子记录 (Fk) 被删除,则允许删除子记录,但不对父 (Pk) 记录执行任何操作(超级重要!)
- 如果删除父记录,则删除它以及所有子表中的所有相关子记录
但是,我正在阅读 SO 和 MySQL 文档上的线程,其中说“NO ACTION”与“RESTRICT”相同,如果我无法删除子记录,这将导致问题。我在我的 PHP 代码中主要使用“INSERT INTO”语句和 ON DUPLICATE KEY UPDATE' 语句。我的倾向是从数据库级别完全删除外键约束,并像我在我的 PHP/PDO 中所做的那样强制执行我想要实现的目标。我实际上正在使用外键约束,因为我认为我必须这样做,但并没有真正明白这一点,因为无论如何更新主键都不应该发生。
做这个的最好方式是什么。如果它实际上是防止而不是保护,那么“不采取行动”的一个好的用例是什么。
解决方案
“NO ACTION”与“RESTRICT”相同,如果我无法删除子记录,这将导致问题。
那不是那个条件的意思。它不会阻止您删除子记录,当且仅当存在依赖于父记录的子记录时,它才会阻止您删除父记录。
例子:
表Orders
与 具有一对多关系LineItems
,并且外键 inLineItems
具有限制选项。
CREATE TABLE Orders (
order_id INT NOT NULL,
PRIMARY KEY (order_id)
);
CREATE TABLE LineItems (
lineitem_id INT NOT NULL,
order_id INT NOT NULL,
PRIMARY KEY (lineitem_id),
FOREIGN KEY (order_id) REFERENCES Orders (order_id) ON DELETE RESTRICT
);
创建一些测试数据:
mysql> INSERT INTO Orders SET order_id = 123;
Query OK, 1 row affected (0.02 sec)
mysql> INSERT INTO LineItems SET lineitem_id = 1, order_id = 123;
Query OK, 1 row affected (0.02 sec)
我们不能删除 Orders 记录,因为有一个 LineItem 依赖于它:
mysql> DELETE FROM Orders WHERE order_id = 123;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`lineitems`, CONSTRAINT `lineitems_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `Orders` (`order_id`))
但是我们可以随时删除 LineItems 记录:
mysql> DELETE FROM LineItems WHERE order_id = 123;
Query OK, 1 row affected (0.01 sec)
现在没有引用 Orders 记录的 LineItems 记录,我们也可以删除该记录:
mysql> DELETE FROM Orders WHERE order_id = 123;
Query OK, 1 row affected (0.01 sec)
推荐阅读
- node.js - 无法在节点上构建 node-re2:12.18.1-alpine docker 映像
- windows - 如何为 Docker 更新 Windows 容器中的路径?
- javascript - 如何编写测试,而不用在 nestjs 中模拟存储库
- typescript - 使用 async/await 链接两个 Promise
- reactjs - 如何仅在条件下处理 useEffect
- python - 通过过滤渲染 jinja2 模板时包含和排除字符串输出
- javascript - 如何在传播运算符 Javascript 中避免 If 和 else
- python - 如何让 Altair 根据指定字段对 y 轴进行排序?
- plot - Julia plots:用反事实值替换真实的刻度值
- r - 在没有信息时为日期和国家添加新行