我正在完成我接管的项目,在数据库方面,我注意到以前的程序员编写了一堆触发器来删除子记录。问题是,这些记录已与我正在删除的父记录具有外键关系。删除触发器只不过是子记录的简单删除语句。
编写触发器以删除子记录是否有好处,或者我可以将其更改为在删除时级联并且没问题吗?
我正在使用MSSQL 2008。
答案 0 :(得分:16)
CASCADE DELETE 只能级联到单个表。如果有两个表与维表的外键关系,则只能将删除级联到其中一个表。 (这是为了防止删除级联多个路径并产生冲突,就像C ++允许多重继承但C#只允许单继承一样)
如果是这种情况,您将被迫使用触发器或专门处理代码中的案例。
出于这个原因,我看到很多人选择在所有情况下使用触发器。即使只有一张外国桌子。这确保了一致性,因此人们知道维护数据库时要查找的内容。
如果可以将删除级联到多个表,我会说这将是最优选的选项。然而,这种限制使水泛滥,我现在更倾向于拥有所有这些行为的触发器。使用触发器进行级联删除和更新的开销在编码方面只是次要的,但允许标准实践真正通用。
修改强>
您可能希望将“已接受的答案”移至其他人,我已经解决了上述问题。
你可以有多个事实表具有ON DELETE CASCADE外键重键对一个标志尺寸表。
你不能做的是有一个事实表对多个维度表有ON DELETE CASCADE外键约束。
所以例如......
- 尺寸表[人物](id INT IDENTITY,)
- 尺寸表[考试](id INT IDENTITY,)
- 面部表[Exam_Score](person_id INT,exam_id INT,得分INT)
如果删除了人员或考试,您还希望删除相关的Exam_Score记录。
这在MS SQL Server中使用ON DELETE CASCADE是不可能的,因此需要触发器。
(向Mehrdad道歉,他试图向我解释这一点,但我完全错过了他的观点。)
答案 1 :(得分:10)
远离不必要的触发器。
如果您需要这样做,请使用ON DELETE CASCADE
。
答案 2 :(得分:1)
我会在删除时使用cascade,但这只是在您删除父级时肯定要删除子级的时候。
如果您有任何条件逻辑(我只删除了在星期日删除的孩子),那么使用触发器。
我只想在开发系统上将其更改为cascade on delete
,然后运行我的单元测试并确保没有任何损坏。
答案 3 :(得分:1)
我几乎同意这里的Dems,除非我尽可能使用ON DELETE CASCADE
(以及ON UPDATE CASCADE
)参考动作,并且只在必要时使用触发器。我还考虑从表中撤销权限并强制使用'helper'存储过程进行删除和更新。
称我为乐观主义者,但我相信a)我的代码将继续移植到未来的MS SQL Server版本中,并且b)SQL Server团队将很快有一天能够解决“一个级联路径”限制,我将用级联参考动作替换触发器:)