2012-04-19 74 views
10

比方说,我有一个层次3个表:INSTEAD OF触发器和CASCADE路径

TableA -> TableB -> TableC 

TableCTableB一个外键关系,并TableBTableA一个外键关系。

如果我删除TableA中的记录,它应该级联删除整个层次结构。使用ON DELETE CASCADE会正常工作。

但是让我们假设我需要在TableC上放置一个INSTEAD OF触发器。我的理解是,INSTEAD OF触发器不能放在具有删除级联的表上。取自MSDN:

对于INSTEAD OF触发器,在具有指定级联动作ON DELETE的参照关系的表上不允许使用DELETE选项。

如果我必须采取级联删除掉TableB->TableC,我需要使用INSTEAD OF触发强制执行参照完整性,然后我有同样的问题与TableB->TableA。这是一个简单的例子,但想象一下级联路径要大得多。它似乎可以在整个漫长的瀑布路径中轻松滚动。

那么,处理这种情况的最佳做法是什么?

+1

你想触发器做什么(而不是删除),不会破坏参照完整性? – 2012-04-19 08:54:09

+0

我想避免在示例中增加更多复杂因素,因为我不是在寻找表格重新设计解决方案,而是针对特定场景的答案。但是作为参考,TableC使用邻接列表模型来存储层次结构。我使用INSTEAD OF触发器递归删除整个层次结构。由于使用SS2005,HierarchyID是不可能的。 – 2012-04-19 09:03:59

+2

没有重新设计表格,这可能会有所帮助:[SQL Server:使用自引用FOREIGN KEY删除](http://explainextended.com/2010/03/03/sql-server-deleting-with-self-referential-外键/) – 2012-04-19 09:13:44

回答

3

假设您必须使用INSTEAD OF触发器,并且AFTER触发器不是一个选项,最好的方法是a)严格控制模式,以便b)以常规方式脚本化INSTEAD OF触发器以实现CASCADE DELETE和其他你需要的操作。

像以前一样创建FK约束,但不包含任何级联行为。在FK名称,使用一些约定,表明应该发生什么样的级联行为和自定义行为,如:

  • FK_UC_DC_Table1_Table2 - 级联更新,删除级联
  • FK_UC_DN_Table1_Table3 - 级联更新,删除设置为null

使用任何有意义的东西,但是创建FK,它们是代码生成的有用元数据,您可以使用FK名称来为代码生成器记录指令。

然后,我会更进一步,并将这些表分离到各自的模式中。它们不会像其他表格那样工作,并且在测试和优化代码生成时,它们将首先变得越来越麻烦。最好保留所有这些隔离,并且容易通过普通容器识别。

专用模式还会通知任何修改数据的人,即不同的规则和行为适用。

3

标准的最佳做法是触发器,而不是定义上意见,而不是

如果您必须在FK更新/删除中使用触发器,最好使用AFTER,因为它始终会执行。

如果您想要取消级联动作但保留FK,只需将FK动作设置为NO ACTION。

+0

不幸的是,AFTER触发器在这种情况下不是解决方案,因为在触发器被触发之前触发完整性将被违反。 – 2012-06-08 07:53:35

+0

你可以更具体地说明你想让触发器做些什么吗? – matchdav 2012-06-08 20:55:11

+0

请参阅问题下的第二条评论。然而,我并不十分关心实施,而是人们会为通用情景做些什么。我很欣赏这可能取决于实施,但仍然! – 2012-06-09 14:53:22

相关问题