多个触发器与单个触发器

Dan*_*Dan 5 trigger sql-server sql-server-2008-r2

设想:

每次在表中插入/更新/删除数据/从表中/从表中插入/更新/删除数据,都需要执行多个不相关的业务逻辑项。

鉴于解决方案是使用数据库触发器,哪个选项更好?:

1) 每个操作一个触发器(插入/更新/删除):

  • I_Table - 在插入上执行
  • U_Table - 在更新时执行
  • D_Table - 在删除时执行

每个触发器将处理多个不相关的业务逻辑项。

或者

2) 每个操作的多个触发器被关注点隔离:

  • I_Table_Logging - 用于登录插入
  • I_Table_RI - 用于在插入上实施参照完整性
  • I_Table_BL - 用于在插入上执行业务逻辑
  • U_Table_Logging - 用于登录更新
  • U_Table_RI - 用于在更新中强制执行参照完整性
  • U_Table_BL - 用于在更新上执行业务逻辑
  • D_Table_Logging - 用于登录删除
  • D_Table_RI - 用于在删除时强制执行参照完整性
  • D_Table_BL - 用于在删除时执行业务逻辑

我更喜欢选项 2,因为单个代码单元有一个关注点。我不是 DBA,对 SQL Server 的了解足以让我变得危险。

不得更改数据库的架构和模式。模式中有几个地方应该使用显式关系强制执行,但不幸的是还不能更改。这就是我需要手动强制执行参照完整性而不是依赖显式关系的原因。

是否有任何令人信服的理由在一个触发器中处理所有问题?我特别关注性能、执行顺序和回滚。

db2*_*db2 6

我个人的偏好是按功能创建触发器,而不是按 DML 操作。所以我有一个处理插入/更新/删除的审计,一个处理某种业务规则或参照完整性(同样,插入/更新/删除),另一个做一些丑陋的 hack 来解决我们客户端软件中的不良行为(可能仅用于插入或更新)等。

将每个“行为”保存在一个地方可以减少忘记更新在三个单独的插入、更新和删除触发器中重复的逻辑的机会。

触发器的最大缺陷是 INSERTED 和 DELETED 表没有索引,你不能直接索引它们。将它们加入大型数据集的性能非常糟糕,当表上有许多触发器时,事情就会变得非常失控,尤其是当触发器级联开始发挥作用时。

我编写的大多数触发器都是通过创建表变量 @i 和 @d 开始的,其中包含将需要的 INSERTED 和 DELETED 列,为它们提供一个聚集主键(因为这是您可以索引表变量的唯一方法),然后填充他们使用来自 INSERTED 和 DELETED 的数据。

我写了一篇关于触发器的简短(非商业性)文章,它还涵盖了其他一些要点。

http://dave.brittens.org/2012/03/29/writing-well-behaved-triggers/


dat*_*god 6

我再怎么强调都不为过:触发器不是业务逻辑的地方!

我只会将触发器用于审计目的(例如上次更新的日期戳)。将业务逻辑放在触发器中乍一看似乎是个好主意,但您将来很可能会一次又一次地踩到自己的脚。触发器往往会被遗忘,并且会开始干扰您以后可能必须执行的其他批量操作。我一次又一次地看到这种情况发生,并听到不幸的 DBA 发出一声惨叫:“哎呀!我忘记了所有这些触发器!!”

将您的业务逻辑移到应用程序中,或者至少移到将进行数据操作的存储过程中。触发器不是它的地方。使用约束来强制执行数据完整性,而不是触发器。

  • 有时,业务逻辑和数据完整性之间只有一线之隔。有时数据完整性所需的东西对于约束来说太复杂了。在这种情况下,我认为触发器是天赐之物。 (2认同)