Sql 而不是触发器和级联路径

Sql 而不是触发器和级联路径,sql,sql-server,triggers,cascade,referential-integrity,Sql,Sql Server,Triggers,Cascade,Referential Integrity,假设我在一个层次结构中有3个表: TableA -> TableB -> TableC TableC与TableB有外键关系,TableB与TableA有外键关系 如果我在表a中删除一条记录,它应该通过层次结构向下级联删除。在DELETE CASCADE上使用,就可以了 但是,假设我需要在表C上放置而不是触发器。我的理解是,不能将而不是触发器放在具有删除级联的表上。摘自MSDN: 对于INSTEAD OF触发器,对于具有指定DELETE时级联操作的引用关系的表,不允许使用DELET

假设我在一个层次结构中有3个表:

TableA -> TableB -> TableC
TableC
TableB
有外键关系,
TableB
TableA
有外键关系

如果我在
表a
中删除一条记录,它应该通过层次结构向下级联删除。在DELETE CASCADE上使用
就可以了

但是,假设我需要在
表C
上放置
而不是
触发器。我的理解是,不能将
而不是
触发器放在具有删除级联的表上。摘自MSDN:

对于INSTEAD OF触发器,对于具有指定DELETE时级联操作的引用关系的表,不允许使用DELETE选项

如果我必须关闭级联删除
TableB->TableC
,我将需要使用
而不是
触发器来强制引用完整性,那么
TableB->TableA
也会遇到同样的问题。这是一个简单的示例,但请想象级联路径要大得多。看起来它很容易在一条长长的瀑布路径上滚雪球


那么,处理这种情况的最佳实践是什么呢?

假设您必须使用而不是触发器,并且AFTER触发器不是一个选项,最好的方法是a)严格控制模式,这样您就可以b)以常规方式编写替代触发器的脚本,以实现级联删除和您需要的任何其他操作

与前面一样创建FK约束,但不包含任何级联行为。在FK名称中,使用某种约定来指示应发生何种级联行为和自定义行为,例如:

  • FK_UC_DC_表1_表2——更新级联,删除级联
  • FK_UC_DN_表1_表3——更新级联,删除集null
使用任何有意义的方法,但一定要创建FK,它们是代码生成的有用元数据,您可以使用FK名称记录代码生成器的指令

然后我会更进一步,将这些表隔离在它们自己的模式中。它们的行为方式与其他表不同,而且在测试和微调代码生成时,它们首先会出现更多的错误。最好将所有这些都隔离,并用一个普通容器容易识别


一个专用的模式还将通知任何修改数据的人应用不同的规则和行为。

标准的最佳实践是在视图而不是表上定义触发器

如果必须在FK更新/删除上使用触发器,最好在之后使用,因为它将始终执行


如果要取消级联操作但保留FK,只需将FK操作设置为“无操作”。

您希望触发器做什么(而不是删除)来不破坏引用完整性?我希望避免给示例增加更多的复杂性,因为我不寻求表重新设计解决方案,而是对具体情况的回答。然而,作为参考,TableC使用邻接列表模型来存储层次结构。我使用INSTEAD OF触发器在层次结构中递归删除。由于使用SS2005,无法使用HierarchyID。如果不重新设计表,这可能会有所帮助:就个人而言,我会使用存储过程来控制删除。没有级联,就没有触发器。触发器就像一个乒乓球扔进满是捕鼠器的房间。不幸的是,在这种情况下,AFTER触发器不是解决方案,因为在触发器被触发之前,引用完整性将被破坏。你能更具体地说明你希望触发器做什么吗?请参阅问题下的第二条注释。然而,我不太关心实现,而是关心在一般场景下人们会做什么。我理解这可能取决于执行情况,但仍然!我看到了,但是,我认为这是不合理的。你应该告诉人们你想做什么。我的答案是最佳实践,但你是说不可能做到这一点,你应该说为什么会这样。事实上,你可能有一个糟糕的设计,你将不得不处理它。有时候,但这不是我问的原因。我只是想知道触发器应该做什么。我的注释指出,表使用邻接列表模型存储层次结构,因此它使用INSTEAD OF触发器来维护RI。i、 e.如果我删除一个父项,我想级联删除该父项的子项。不能使用AFTER触发器,因为在执行触发器之前,删除时会违反RI。