外键约束可能会导致循环或多个级联路径?


176

当我尝试向表中添加约束时出现问题。我得到了错误:

在表“ Employee”上引入FOREIGN KEY约束“ FK74988DB24B3C886”可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。

我的约束是在一个Code表和一个employee表之间。该Code表包括IdNameFriendlyNameTypeValue。的employee具有多个字段的标号,从而可以存在对于每种类型的码的参考的。

如果引用的代码被删除,则需要将字段设置为null。

有什么想法可以做到吗?


解决方案之一就在这里
IsmailS

Answers:


180

SQL Server会简单地计算级联路径,而不是尝试找出是否存在任何实际的循环,而是假定最坏的情况并拒绝创建引用动作(CASCADE):您可以并且应该仍然创建没有引用动作的约束。如果您不能更改设计(或这样做会损害性能),那么您应该考虑使用触发器作为最后的选择。

FWIW解决级联路径是一个复杂的问题。其他SQL产品将简单地忽略该问题,并允许您创建周期,在这种情况下,人们将竞相竞猜哪个周期将最后覆盖值,这可能是设计者的无知(例如ACE / Jet这样做)。我了解某些SQL产品将尝试解决简单的情况。事实仍然存在,SQL Server甚至没有尝试,通过禁止多个路径来发挥它的超安全性,至少它告诉您了这一点。

Microsoft自己建议使用触发器而不是FK约束。


2
我仍然无法理解的一件事是,如果可以通过使用触发器来解决此“问题”,那么触发器为什么不会“导致循环或多个级联路径...”呢?
armen 2014年

5
@armen:因为您的触发器将显式提供系统无法自行隐式找出的逻辑,例如,如果存在删除引用操作的多个路径,则您的触发器代码将定义要删除的表和顺序。
2014年

6
并且触发器在第一个操作完成后执行,因此不会发生比赛。
2015年

2
@dumbledad:我的意思是,仅在约束(可能是组合条件)无法完成工作时才使用触发器。约束是声明性的,其实现是系统的责任。触发器是过程代码,您必须对实现进行编码(和调试),并忍受其缺点(性能更差等)。
一天,2016年

1
问题在于,触发器只有在删除外键约束后才起作用,这意味着您对数据库插入没有参照完整性检查,因此需要更多的触发器来处理它。触发器解决方案是一个导致简化的数据库设计的难题。
Neutrino
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.