Предположим, что у вас есть таблицы 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
в обоих триггерах.