9

设想:

每次将数据插入/更新/删除到/从表中/从表中,最多需要发生 3 件事:

  1. 数据需要记录到单独的表中
  2. 必须对隐式相关数据强制执行引用完整性(我指的是应该与外键关系链接的数据,但不是:例如,当更新Table1.Name也应该更新Table2.Name为相同的值时)
  3. 任意业务逻辑需要执行

不得更改数据库的体系结构和模式,并且必须使用触发器来完成要求。

问题

哪个选项更好?:

  1. 每个操作(插入/更新/删除)的单个触发器处理多个关注点(日志、强制执行隐式引用完整性和执行任意业务逻辑)。此触发器可以命名D_TableName(“D”表示删除)。
  2. 每个操作的多个触发器按关注点隔离。他们可以被命名为:

    • D_TableName_Logging- 用于在删除某些内容时进行记录
    • D_TableName_RI
    • D_TableName_BL

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

是否有任何令人信服的理由可以在一个触发器中处理所有问题?

4

4 回答 4

4

哇,你处于一个没有胜利的境地。曾经要求通过触发器完成所有这些事情的人应该被枪杀然后被解雇。通过触发器执行 RI?

你说数据库的架构和模式不能改变。但是,通过创建触发器,您至少是在更改数据库的架构,并且可以说是架构。

我可能会选择选项 #1 并创建额外的存储过程和 UDF 来处理日志记录、BL 和 RI,这样代码就不会在各个触发器之间重复(触发器将调用这些存储的过程和/或 UDF)。我真的不喜欢按照您在选项 2 中提出的方式命名触发器。

顺便说一句,请告诉您组织中的某个人,这太疯狂了。RI 不应通过触发器强制执行,并且业务逻辑不属于数据库。

于 2013-01-03T19:11:10.030 回答
4

在一个触发器中完成所有操作可能会更有效,因为您最终可能会对(未索引的)inserteddeleted表进行更少的操作。

此外,当您有多个触发器时,可以设置第一个和最后一个触发,但任何其他触发器将以任意顺序触发,因此如果您有超过 3 个特定操作的触发器,您将无法确定性地控制事件顺序。

如果这些考虑都不适用,那么这只是一个偏好问题。

当然,不用说使用触发器执行此操作的规范很糟糕。

于 2013-01-03T19:11:35.503 回答
2

我同意@RandyMinder。但是,我会更进一步。触发器不是处理这种情况的正确方法。您描述的逻辑对于触发机制来说太复杂了。

您应该在存储过程中包装插入/更新/删除。这些存储过程可以管理业务逻辑和日志记录等。此外,它们使正在发生的事情变得显而易见。调用存储过程的存储过程链是显式的。调用触发器的触发器链由不显式调用触发器的插入/更新/删除语句确定。

触发器的问题在于它们在不同的表之间引入了依赖关系和锁定,并且解开依赖关系可能是一场噩梦。同样,当问题可能位于触发器调用触发器调用存储过程调用触发器时,确定性能瓶颈可能是一场噩梦。

于 2013-01-03T19:17:52.493 回答
0

如果您使用 Microsoft SQL Server 并且能够修改执行 DML 语句的代码,则可以使用OUTPUT 子句将更新、插入、删除的值转储到临时表或内存变量中,而不是触发器中。这将使性能损失降到最低。

于 2016-03-10T01:57:50.727 回答