当前位置:  开发笔记 > 数据库 > 正文

防止相互递归执行触发器?

如何解决《防止相互递归执行触发器?》经验,为你挑选了1个好方法。

假设你有表格PresentationsEvents.保存演示文稿并包含基本事件信息(如位置和日期)时,将使用触发器自动创建事件.(我担心技术原因不可能简单地将数据保存在一个地方并使用视图.)此外,当在演示文稿中稍后更改此信息时,触发器也会将更新复制到事件中,像这样:

CREATE TRIGGER update_presentations
ON Presentations
AFTER UPDATE
AS
BEGIN
    UPDATE Events
    SET Events.Date = Presentations.Date,
        Events.Location = Presentations.Location
    FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID
    WHERE Presentations.ID IN (SELECT ID FROM inserted)
END

现在,客户想要它,以便如果用户更改了事件中的信息,它也应该返回到演示文稿.出于显而易见的原因,我不能这样做:

CREATE TRIGGER update_events
ON Events
AFTER UPDATE
AS
BEGIN
    UPDATE Presentations
    SET Presentations.Date = Events.Date,
        Presentations.Location = Events.Location
    FROM Events INNER JOIN Presentations ON Events.PresentationID = Presentations.ID
    WHERE Events.ID IN (SELECT ID FROM inserted)
END

毕竟,这会导致每个触发器相互触发.我能做的是last_edit_by向两个表添加一个包含用户ID的列.如果触发器使用特殊的无效ID填充(例如,通过使实际人员的所有用户ID为正,但脚本的用户ID为负数),我可以将其用作退出条件:

    AND last_edit_by >= 0

这可能有用,但我想做的是向SQL服务器指出,在事务中,触发器应该只触发一次.有没有办法检查这个?或者也许要检查一个表是否已经受到触发器的影响?


感谢史蒂夫罗宾斯:

只需将可能嵌套的UPDATE语句包装在IF条件中检查即可trigger_nestlevel().例如:

CREATE TRIGGER update_presentations
ON Presentations
AFTER UPDATE
AS
BEGIN
    IF trigger_nestlevel() < 2
        UPDATE Events
        SET Events.Date = Presentations.Date,
            Events.Location = Presentations.Location
        FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID
        WHERE Presentations.ID IN (SELECT ID FROM inserted)
END

请注意,trigger_nestlevel()似乎是从1开始,而不是从0开始.如果您希望两个触发器中的每一个都执行一次,但不是更频繁,只需检查trigger_nestlevel() < 3两个触发器.



1> Steven Robbi..:

我不确定每次交易都这样做,但你是否需要为其他部分启用嵌套触发器?如果在服务器上关闭它们,则触发器不会从更新表的另一个触发器触发.

编辑(回答评论):您需要更改触发器A以使用TRIGGER_NESTLEVEL

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有