T-SQL:在修改事务结束之前运行的触发器

时间:2015-05-21 15:29:28

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

问题陈述

我有一个从3个不同的大表到​​非常大的表递归收集和聚合信息的视图。此视图本身需要相当长的时间来执行,但在许多select语句中需要并且经常执行。

然而,生成的视图非常小(2列中有一些dozend结果)。

所有更新操作通常都会启动一个事务,执行数千个INSERT,然后提交事务。这种情况不会经常发生,但如果将某些内容写入数据库,则通常会有大量数据。

我尝试了什么

  1. 由于视图很小,不经常更改并经常阅读,我想到了创建索引视图。但是,遗憾的是,您无法使用CTE或甚至递归CTE创建索引视图。
  2. 要模仿'在索引或物化视图中,我考虑编写一个执行视图的触发器,并在每次修改一个基表时将结果存储到表中。但是,我想如果大量的条目是UPDATEed或INSERTed并且触发器在这些表上运行每个INSERT / UPDATE语句,即使它们在单个事务中,也会永远这样。
  3. 实际问题

    是否有可能在提交之前和事务的最后一次插入/更新语句完成之后编写一个一次的触发器,并且只有当任何一个语句改变了这三个表中的任何一个时?

2 个答案:

答案 0 :(得分:3)

不,没有直接的方法来制作在交易结束前运行的触发器。每次触发DML语句(INSERTUPDATEDELETE)时,DML触发器运行一次,并且没有其他类型的触发器与数据修改相关。

间接地,您可以将所有INSERT插入到临时表中,然后将它们从#temp表中一起插入到真实表中,从而导致该表触发一个触发器。但是如果你要写多个表,你仍会遇到同样的问题。

SOP(标准操作实践)解决此问题的方法是让存储过程预先处理所有事情,而不是尝试捕获背面的所有内容的触发器。

如果数据一致性很重要,那么我建议您遵循上面提到的存储过程中的SOP方法。以下是这种方法的高级概述:

  1. 使用将所有更改首先转储到#temp表中的存储过程
  2. 然后开始交易,
  3. 然后进行更改,将数据/更改从#temp表移动到实际表中,
  4. 然后在触发器中执行您想要的后续工作。如果这些是一致性检查,那么如果它们失败,您应该回滚事务。
  5. 否则,它会提交交易。
  6. 这几乎总是如此正确地完成这样的事情。

答案 1 :(得分:1)

如果您的视图很小并且经常查询并且您的下划线表很少更改,则您不需要“视图”。相反,您需要一个具有相同视图结果的摘要表,并通过每个下划线表上的触发器进行更新。

每次进行数据修改(插入,删除和更新)时都会触发触发器,但一次修改只会触发一次,无论是更新一个记录还是一百万行。您无需担心更新的大小。相反,更新的频率是您的关注点。

如果您的程序定期插入大量行或逐行更新大量行,则可以在更新之前更改过程并禁用触发器,以便仅在过程结束之前更新摘要表,您可以在其中调用相同的“总和”过程并启用这些触发器。

如果您必须始终保持“摘要”最新,即使在大量交易中(我怀疑它是非常有用或实际的,如果您的视图执行缓慢),您可以禁用这些触发器,在每次交易后自己做一些计算,在每个交易后,在你的程序中更新汇总表。