【发布时间】: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