假设您有表Presentations
和Events
。保存演示文稿并包含基本事件信息(如位置和日期)时,将使用触发器自动创建事件。 (我担心技术原因不可能简单地将数据保存在一个地方并使用视图。)此外,当在演示文稿中稍后更改此信息时,触发器也会将更新复制到事件中,像这样:
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服务器表明,在事务中,触发器应该只触发一次。有没有办法检查这个?或者也许要检查表是否已经受到触发器的影响?
回答感谢Steve Robbins:
将可能嵌套的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
。
答案 0 :(得分:19)
我不确定每次交易都这样做,但你是否需要为其他部分启用嵌套触发器?如果在服务器上关闭它们,则触发器不会从更新表的另一个触发器触发。
编辑(评论回答):您需要更改触发器A以使用TRIGGER_NESTLEVEL