在2005年MSSQL我只是击中了臭名昭著的错误信息:
上表YYY将外键约束XXX可能导致循环或多个级联路径。 指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。
现在,StackOverflow上大约有此错误消息几个主题,所以我已经得到了解决(在我来说,我将不得不使用触发器),但我很好奇,为什么会有这样的问题都没有。
据我所知,基本上有他们要避免两种情况 - 一个周期,多条路径。 一个循环将在两个表已级联外键给对方。 OK,一个周期可以跨越几个表了,但是这是基本的情况,并会更容易分析。
当TableA中有外键表B和表C,并表B也有外键的表C的多条路径将是。 同样 - 这是最低限度的基本情况。
我看不到时,记录将在任何这些表中被删除或更新的话会产生任何问题。 当然,你可能需要在同一个表多次查询,看看哪些记录需要更新/删除,但事实是否真的有问题? 这是一个性能问题?
在其他SO话题的人用级联作为“走出去尽可能标注有风险 ”,并指出“ 解决级联路径是一个复杂的问题 ”。 为什么? 哪里是风险? 问题出在哪儿?
你必须与同一母公司2条级联路径的子表:一个“删除”,一个“空”。
什么优先? 你有什么期望后来呢? 等等
注:触发器是代码,并可以添加一些智力或条件级联。
我们禁止使用级联删除的原因有业绩和锁定做。 是的,当你删除一个记录,但迟早你将需要删除一大群的记录和你的数据库将进入静止状态它不是那么糟糕。
如果要删除足够的记录,SQL Server可能会升级到表锁,直到它完成无人能与表做任何事情。
最近,我们搬到我们的客户之一,以他自己的服务器。 作为交易的一部分,我们也只好再删除所有的客户端的记录形成了我们原来的服务器。 删除分批他所有的信息(以便不影响到其他用户的问题)花了几个月。 如果我们的级联删除设置,数据库会一直无法访问其他客户端的数以百万计的记录在一个事务中被删除,数百个表被锁,直到事务做了很长时间。
我还可以看到一个死锁可能在使用级联删除,因为我们有在级联路径将采取与我们的数据库是有点用的clientid在大多数表出现非规范化的秩序无法控制已经发生的情况。 所以,如果它锁定了一个表中有一个外键也到第三个表,以及这是在不同的充路径客户表,它可能无法检查表,以便从第三表中删除,因为这是所有一个事务和锁将不会被释放,直到它被完成。 所以可能它不会让我们设置,如果它看到了交易产生死锁的可能性级联删除。
另一个原因,以避免级联删除的是,有时一个孩子记录的存在是有足够的理由不删除父记录。 举例来说,如果你有一个客户表和客户已经有订单在过去,你不会想删除他,失去了实际订单上的信息。
考虑员工的表:
CREATE TABLE Employee
(
EmpID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL,
MgrID INTEGER NOT NULL REFERENCES Employee(EmpID) ON DELETE CASCADE
);
INSERT INTO Employees( 1, "Bill", 1);
INSERT INTO Employees( 23, "Steve", 1);
INSERT INTO Employees(234212, "Helen", 23);
现在假设比尔退休:
DELETE FROM Employees WHERE Name = "Bill";
Ooooppps; 大家刚刚解雇了!
[ 我们可以辩论的语法的详细信息是否正确; 概念看台上,我想。 ]
我认为问题是,当你做一个路径“ON DELETE CASCADE”,另一个“ON DELETE RESTRICT”,或“不采取行动”的结果(结果)是unpredicable。 这要看删除触发(这也是一个触发,但一个你不必建立自己)将首先执行。
我同意瀑布是“危险的”,应当避免。 (我个人比较喜欢级联的变化而手动具有SQL Server自动照顾他们)。 这也是因为,即使SQL服务器中删除数百万行,输出仍然会显示为
(1行(一个或多个)受影响)
我认为,无论是否使用ON DELETE CASCADE选项是要实现商业模式的问题。 两个业务对象之间的关系可以是一个简单的“关联”,其中的关系的两端是相关的,但在其他独立的对象生命周期这些都是不同的,并且由其它逻辑控制。 有,但是,也“聚合”的关系,其中一个对象实际上可能被视为“父母”和“儿童”的“所有者”或“详细”的对象。 有一个“组合物”的关系,其中一个对象单独存在为多个部件组成的组合物中的更强大的概念。 在“关联”的情况下,你通常不会宣布一个ON DELETE CASCADE约束。 对于聚合或组合物,然而,ON DELETE CASCADE可以帮助您更准确地映射你的商业模式到数据库,并以声明的方式。 这就是为什么它惹恼我,MS SQL Server的限制使用此选项到一个级联路径。 如果我没有记错,许多其他被广泛使用的SQL数据库系统不强加这样的限制。