多个触发器与单个触发器

时间:2013-01-03 19:06:19

标签: sql sql-server triggers sql-server-2008-r2

情境:

每次在表格中插入/更新/删除数据时,最多需要做3件事:

  1. 需要将数据记录到单独的表中
  2. 必须对隐式相关数据强制执行参照完整性(我指的是应该与外键关系链接的数据,但不是:例如。当更新Table1.Name也应该更新{{1 }}到相同的值)
  3. 需要执行任意业务逻辑
  4. 不得更改数据库的体系结构和架构,并且必须使用触发器来完成要求。

    问题

    哪个选项更好?:

    1. 每个操作(插入/更新/删除)的单个触发器,用于处理多个问题(日志,强制隐式参照完整性,并执行任意业务逻辑)。此触发器可以命名为Table2.Name(“D”表示删除)。
    2. 每个操作的多个触发器被关注隔离。它们可以命名为:

      • D_TableName - 用于从
      • 删除内容时进行记录
      • D_TableName_Logging
      • D_TableName_RI
    3. 我更喜欢选项2,因为单个代码单元只有一个问题。我不是DBA,对SQL Server足够了解,让我很危险。

      是否有任何令人信服的理由来处理单个触发器中的所有问题?

4 个答案:

答案 0 :(得分:4)

哇,你处于一种不赢的局面。谁曾要求通过触发器完成所有这些工作应该被拍摄然后被解雇。通过触发器执行RI?

您说不得更改数据库的体系结构和架构。但是,通过创建触发器,您至少可以更改数据库的模式,并且可以认为是架构。

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

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

答案 1 :(得分:2)

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

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

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

当然,毫无疑问,使用触发器执行此操作的规范很糟糕。

答案 2 :(得分:2)

我同意@RandyMinder。但是,我会更进一步。触发器不是解决这种情况的正确方法。您描述的逻辑对于触发机制而言过于复杂。

您应该在存储过程中包装插入/更新/删除。这些存储过程可以管理业务逻辑和日志记录等。此外,他们明确了解正在发生的事情。调用存储过程的一系列存储过程是显式的。调用触发器的触发器链由insert / update / delete语句确定,这些语句不会显式调用触发器。

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

答案 3 :(得分:0)

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