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 的了解足以让我变得危险。
不得更改数据库的架构和模式。模式中有几个地方应该使用显式关系强制执行,但不幸的是还不能更改。这就是我需要手动强制执行参照完整性而不是依赖显式关系的原因。
是否有任何令人信服的理由在一个触发器中处理所有问题?我特别关注性能、执行顺序和回滚。
我个人的偏好是按功能创建触发器,而不是按 DML 操作。所以我有一个处理插入/更新/删除的审计,一个处理某种业务规则或参照完整性(同样,插入/更新/删除),另一个做一些丑陋的 hack 来解决我们客户端软件中的不良行为(可能仅用于插入或更新)等。
将每个“行为”保存在一个地方可以减少忘记更新在三个单独的插入、更新和删除触发器中重复的逻辑的机会。
触发器的最大缺陷是 INSERTED 和 DELETED 表没有索引,你不能直接索引它们。将它们加入大型数据集的性能非常糟糕,当表上有许多触发器时,事情就会变得非常失控,尤其是当触发器级联开始发挥作用时。
我编写的大多数触发器都是通过创建表变量 @i 和 @d 开始的,其中包含将需要的 INSERTED 和 DELETED 列,为它们提供一个聚集主键(因为这是您可以索引表变量的唯一方法),然后填充他们使用来自 INSERTED 和 DELETED 的数据。
我写了一篇关于触发器的简短(非商业性)文章,它还涵盖了其他一些要点。
http://dave.brittens.org/2012/03/29/writing-well-behaved-triggers/
我再怎么强调都不为过:触发器不是业务逻辑的地方!
我只会将触发器用于审计目的(例如上次更新的日期戳)。将业务逻辑放在触发器中乍一看似乎是个好主意,但您将来很可能会一次又一次地踩到自己的脚。触发器往往会被遗忘,并且会开始干扰您以后可能必须执行的其他批量操作。我一次又一次地看到这种情况发生,并听到不幸的 DBA 发出一声惨叫:“哎呀!我忘记了所有这些触发器!!”
将您的业务逻辑移到应用程序中,或者至少移到将进行数据操作的存储过程中。触发器不是它的地方。使用约束来强制执行数据完整性,而不是触发器。