Предположим, у вас есть таблицы 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
в обе таблицы, содержащий идентификатор пользователя. Если заполняется триггером со специальным недействительным идентификатором (скажем, делая все идентификаторы пользователей реальных людей положительными, а идентификаторы сценариев - отрицательными), я мог бы использовать это как условие выхода:
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
в обоих триггерах.