【问题标题】:Multiple triggers vs a single trigger多个触发器与单个触发器
【发布时间】:2012-12-18 04:50:08
【问题描述】:

场景:

每次将数据插入/更新/删除到/从表中/从表中,最多需要发生 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 的了解足以让我变得危险。

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

【问题讨论】:

  • 这是一个高交易量的数据库吗?
  • 数据库有100个并发用户。
  • 我会非常担心由级联触发器引起的性能瓶颈,尤其是在可能有几十个用户同时修改数据库的情况下。
  • "一个函数应该只做一件事"
  • @NeilMcGuigan - 不一定适用于 SQL。我不想为了避免违反 SRP 而在多个不同的触发器中多次扫描同一个表或多次更新同一行中的不同列。

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


【解决方案1】:

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

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

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

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

【讨论】:

  • 这里存储过程和 UDF 的问题是它们无法访问 inserteddeleted,除非您要将它们复制到 TVP 中。
  • @MartinSmith - 或者先将它们放在临时表中。鉴于提出的要求很少,很难说什么是正确的方法。
  • @RandyMinder - 函数无法访问#temp 表。
  • @MartinSmith - 是的,这是真的。 UDF 在这种情况下可能不起作用,如果存储过程可以完成这项工作,则可能没有必要。
  • 业务逻辑属于业务想去的地方。
【解决方案2】:

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

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

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

当然,使用触发器执行此操作的规范很烂。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 我完全同意你的观点,触发器不是应该如何处理的。要求的原因与支持旧解决方案有关。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2012-10-21
      • 1970-01-01
      • 2023-03-19
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多