【问题标题】:T-SQL trigger effect a change before calling other code调用其他代码之前的 T-SQL 触发器效果更改
【发布时间】:2010-11-23 04:46:26
【问题描述】:

我有一个表,我们称之为 [MYTABLE],带有一个 FOR INSERT, UPDATE 触发器。

触发器需要执行一个存储过程,它会根据对[MYTABLE]所做的更改做一些工作。我无法将存储过程的代码移到触发器中。

到目前为止,一切都很好...由于触发器在进行更改后执行,因此存储过程无需访问 [inserted] [已删除] 元表。

但是...触发器需要更改一个附加字段[LastModified] smalldatetime),以便存储过程可以在其处理中使用该数据。这不是,因此存储过程可以看到插入/更新的内容...该过程可能会根据未包含在触发它的更新中的其他记录执行许多操作。

问题是,如果我的触发器改变了[LastModified],那要么什么都不做(如果我关闭了递归触发器),要么它会结束调用存储过程两次——一次是因为原始触发更改,另一次是因为我对 [LastModified] 的更改。

我该如何解决这个问题,以便 (a) [LastModified] 每次更改都会更新,并且 (b) 存储过程仅在 it 有权访问[LastModified] 的新值?

我正在考虑两个想法,但它们闻起来很有趣,所以我宁愿看看是否有更直接的解决方案。

编辑:

好的,以下是我目前的解决方案,也许对讨论有帮助:

1.使用两个触发器。一个是“INSTEAD OF”触发器,它将处理用户对记录的更新并更改 LastModified,但如果更新来自 SP(它可以根据修改了哪些列来判断)。另一个是“AFTER”触发器,它将调用 EXEC。此触发器使用 INSTEAD OF 触发器已应用的 LastModified 列获取更新。至少我希望它是这样工作的。

2。将 ModifiedDate 移动到另一个表。这样,我可以有一个 AFTER INSERT/UPDATE 触发器,只有如果用户启动 INSERT/UPDATE,将审计记录添加到另一个表并调用 SP。然后 SP 会修改其他记录,这会导致触发器再次触发,但它会很快识别情况并返回而不做更多工作。

第一个解决方案的缺点是我必须在触发器中维护一个列列表,因此 INSTEAD OF 更新实际上可以完成预期的工作(因为我要在列表中添加一个列,ModifiedDate,我不能只是INSERT INTO tbl FROM FROM 已插入,我必须指定列)。

【问题讨论】:

  • 如何执行初始插入/更新?你必须使用触发器吗?我问的原因是整个事件过程可以封装在一个存储过程中(根本不需要触发器)。

标签: sql sql-server tsql triggers


【解决方案1】:

您是否尝试过 IF UPDATE(LastModified) 指令?

CREATE TRIGGER XYZ ON MYTABLE 
FOR INSERT, UPDATE 
AS 
BEGIN 
IF UPDATE(LastModified) 
  RETURN 
ELSE 
  BEGIN
    UPDATE MYTABLE SET LastModified = GETDATE() 
    FROM MYTABLE INNER JOIN INSERTED ON MYTABLE.ID = INSERTED.ID
    EXEC TheStoreProc
  END
END;

【讨论】:

  • 这解决了在工作流的错误一侧调用 EXEC 的问题,但实际上并没有更改 LastModified,它需要由触发器更新。
  • 修复了脚本,现在更新表,然后执行脚本。触发器会被“触发”两次,但内部执行会立即结束。
  • Rodrigo-- 谢谢,但是如果这样做了,EXEC 会“看到”LastModified 的变化吗?它会看到它是有道理的,除非触发器在某种隐含事务中工作。
  • 这与我最终所做的足够接近,所以我接受它作为正确答案。对我来说唯一的区别是 INSERT will 为 UPDATE(LastModified) 返回 TRUE,我需要这些调用来跳过 LastModified 上不必要的 UPDATE(因为它已经在插入时默认设置),但它应该调用存储过程。
【解决方案2】:

我不确定我是否理解您所描述的流程。是吗:

  1. 记录已更新
  2. 调用了更新触发器过程
  3. 触发更新 LastModified 字段
  4. 触发器调用另一个过程

应该可以正常工作,只要“另一个过程”不更新同一个表, 这将再次触发触发器。

如果“另一个过程”正在再次更新表,您可能会移动这些更新 在调用“另一个过程”之前进入触发器。

这有什么帮助吗?

【讨论】:

  • 不幸的是,这正是正在发生的事情。 SP 将从不更新 same 记录作为“原始”触发器,但它会更新其他记录,这将再次调用触发器。所以,虽然没有递归的机会,但它仍然是一个混乱的小单步循环。而且,不幸的是,将 SP 代码移动到触发器中并没有什么好处(因为 SP 只影响 other 记录,INSTEAD OF 触发器不会减少单步递归)并且会使代码更少可维护(多个表上的触发器调用相同的 SP)。我宁愿使用视图,但这次不要打电话了。
猜你喜欢
  • 2021-08-04
  • 2014-11-11
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多