【问题标题】:When do triggers fire and when don't they触发器什么时候触发,什么时候不触发
【发布时间】:2010-11-18 01:21:03
【问题描述】:

关于 SQL Server 2005 中的触发器的非常普遍的问题。

什么情况下会触发表触发器,什么情况下不会触发?

任何要演示的代码示例都会很棒。

我正在编写一个基于审计的数据库,只是想了解任何可能不会触发我为更新、删除和插入表而设置的触发器的情况。

我的意思的一个例子,

UPDATE MyTable SET name = 'test rows' WHERE id in (1, 2, 3);

以下语句只触发一次更新触发器。

【问题讨论】:

标签: sql-server database triggers audit


【解决方案1】:

你希望他们什么时候开火?

CREATE TRIGGER AFTER ACTION

在提交操作 (insert update delete) 之后运行。 INSTEAD OF 触发触发器代替操作。

触发器的最大问题之一是它们会在执行操作时触发,即使没有行受到影响。这不是错误,如果您不小心,它会很快烧毁您。

此外,对于触发器,您将使用 inserteddeleted 表。更新的行都列在两者中。这让很多人望而却步,因为他们不习惯将update 视为delete 然后insert

MSDN 文档实际上对触发器何时触发以及它们有什么影响进行了相当深入的讨论here

【讨论】:

  • 你能举一个例子来说明当没有行受到影响时触发器如何产生问题?谢谢。
  • 看看这个:sqlfiddle.com/#!6/be3d3/3。我已经看到计划触发向人们发送电子邮件的触发器。如果您有一个空闲插入或更新记录的进程,这些记录很少影响一行,但只是轮询它,那会很快烧毁您。根据经验,请始终检查触发器中的行是否受到影响!
  • 执行 'UPDATE' 时是否会触发由 'CREATE TRIGGER AFTER INSERT ...' 创建的触发器?你提到 UPDATEdelete 然后是 insert 所以我认为是但没有明确提及。
  • @JohnCarpenter - 否 - 该操作与发出的 SQL 动词一致。他的意思是每当我们说“更新”时,sql server 都会保留一个“之前”副本(已删除的表)和一个“之后”副本(插入的表),它与您更新的表的架构相匹配。这些表(插入的、删除的)仅在 UPDATE 内部可用(因此,在 TRIGGER 本身内部)。每个触发器只会在您告诉它时触发(例如,INSERT、UPDATE 或 DELETE)。
  • @JohnCarpenter - 我还应该提到:INSERT 操作包括插入的表(又名伪表),而 DELETE 操作包括已删除的表。只有 UPDATE 两者都有(因为在 UPDATE 期间总是有“之前”和“之后”)。
【解决方案2】:

我想我会从链接中突出显示 Eric 发布的触发器不会触发的情况:

虽然 TRUNCATE TABLE 语句实际上是 DELETE,但它无法激活触发器,因为该操作不会记录单个行删除。但是,只有对表具有执行 TRUNCATE TABLE 权限的人员才需要担心使用 TRUNCATE TABLE 语句无意中规避了 DELETE 触发器。

【讨论】:

    【解决方案3】:

    在 2008 上你可以使用内置的Change Data Capture

    还有很多情况下触发器不触发,例如:

    · 一个表被删除。

    · 表被截断。

    · 嵌套和/或递归触发器的设置可防止触发器触发。

    · 数据被批量加载,绕过触发器。

    【讨论】:

      【解决方案4】:

      以下语句只触发一次更新触发器。

      无论有多少行受到影响,任何操作类型的语句都只会触发一次触发器,必须编写触发器来处理多行插入/更新/删除。

      如果您的触发器一次仅依赖于插入或删除的伪表中的一行,它将失败。更糟糕的是,它不会因错误而失败,它根本不会影响您希望受触发器影响的所有行。不要通过触发器中的循环或光标修复此问题,请更改为基于集合的逻辑。触发器中的游标可以使您的整个应用程序急速停止,而 500,000 条记录的事务处理并锁定表数小时。

      通过触发器批量插入,除非您指定使用它们。请注意这一点,因为如果您让它们绕过触发器,您将需要代码来确保触发器中发生的任何事情也发生在批量插入之后。或者您需要使用 FIRE_TRIGGERS 选项调用批量插入。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-08
        • 2017-11-20
        • 1970-01-01
        • 1970-01-01
        • 2014-02-04
        • 2011-04-27
        相关资源
        最近更新 更多