如何应用约束和使用"不采取行动"规则意味着"不采取任何行动"



我正在努力澄清外键约束的正确使用,并在"ON DELETE"NO ACTION"时保持空白我将保持通用性,因为它非常简单,不需要深入到有限的细节中。

我有一个父表,它有5个子表-存在所有表中的数据(这不是新的DB构建(。我想设置一切都合乎逻辑,以满足我的客户的需求和我的期望!所有父表到子表都存在一对多关系因此:可以有零个或多个与父表相关的记录主键记录。永远不可能有不与父记录相关(我已经检查过以确保是这样(。

由于现在任何子表中可能(也可能(没有和子记录的父记录,因此设置"父-子"约束失败,好吧,我理解原因,没问题。如此糟糕地设置了儿童对父母的约束:

  • 如果更新了子记录(Fk(,则将父记录(PK(更新为相同记录
  • 如果删除了子记录(Fk(,则允许删除该子记录,但不对父记录(Pk(采取任何操作(非常重要!(
  • 如果删除了父记录,则删除该记录以及所有子表中的所有相关子记录

然而,我在SO和MySQL文档上读取的线程中说"NO ACTION"与"RESTRICT"相同,如果我不能删除子记录,这将导致问题。我在PHP代码中主要使用"INSERT INTO"语句和"ON DUPLICATE KEY UPDATE"语句。我倾向于从DB级别完全删除外键约束,并强制执行我在PHP/PDO中想要实现的目标。我实际上是在使用外键约束,因为我认为我必须这样做,但并没有真正理解这一点,因为无论如何都不应该更新主键。

最好的方法是什么。如果"不采取行动"实际上是预防而不是保护,那么它是一个好的用例。

"NO ACTION"与"RESTRICT"相同,如果我不能删除子记录,这将导致问题。

这不是那个条件的意思。它不会阻止您删除记录,当且仅当存在依赖于父记录的子记录时,它会阻止您删除父纪录。

示例:

OrdersLineItems具有一对多关系,而LineItems中的外键具有restrict选项。

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)

我们无法删除订单记录,因为有一个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)

现在没有引用订单记录的LineItems记录,我们也可以删除该记录:

mysql> DELETE FROM Orders WHERE order_id = 123;
Query OK, 1 row affected (0.01 sec)

@Bill Karwin和这个问题的贡献者。从那以后,我意识到数据库设置不正确,这就是为什么我需要删除FK约束才能使用它。数据库是从MS Access迁移的,除了一些数据类型差异外,在将数据库导入mySQL时,外键约束检查被关闭,而不进行此导入是不可能的。仅此一点就表明MS Access中设置的约束规则存在问题。

现在在MySQL中使用导出的数据库显示了许多孤立记录和索引字段,这些记录和字段已经违反了FK约束,为null或空!-关于修复这些问题并正确规范DB/表,这里的建议是成立的。

感谢您的意见。

最新更新