2013-09-10 6 views
2

Я хочу скопировать содержимое столбца в другой столбец в той же таблице. Поэтому я создал этот триггер:SQL Server Trigger не запускается после вставки и обновления

ALTER TRIGGER [dbo].[kennscht_copy_to_prodverpt] 
ON [dbo].[Stammdaten] 
AFTER INSERT 
AS 
UPDATE Stammdaten 
SET PRODVERPT = (SELECT KENNSCHT FROM INSERTED) 
WHERE SNR = (SELECT SNR FROM INSERTED); 

Но когда я использую UPDATE на столе, чтобы обновить KENNSCHT другое значение, PRODVERPT не обновляется, а также. Теперь, вы можете возразить, что это потому, что триггер находится на AFTER INSERT и не AFTER UPDATE, но когда я изменить его так, что это вызвано UPDATE и INSERT всякий раз, когда я обновить все строки, я получаю сообщение об ошибке из SQL Server

Невозможно обновить строку, потому что это сделает строку уникальной или обновит несколько строк (2 строки) [sic]

Что здесь происходит? Либо триггер ничего не делает, либо он испортил всю таблицу, делая ее не обновляемой.

Обновление: Я также попытался следующий триггер:

UPDATE s 
SET s.PRODVERPT = i.KENNSCHT 
FROM Stammdaten s 
INNER JOIN INSERTED i ON i.SNR = s.SNR; 

Но он имеет точно такое же поведение. Если я использую только AFTER INSERT, ничего не меняется, и если я использую AFTER INSERT, UPDATE, я получаю сообщение об ошибке выше.

Обновление 2: в таблице нет нескольких строк, я уже проверил это, потому что думал, что он может быть связан с проблемой.

+4

Ваш триггер сломана - это предполагает, что 'inserted' содержит только одну строку. Было бы лучше переключиться на стиль 'FROM' /' JOIN' для обновления, чтобы вы могли 'JOIN' с' вставленными', но это не похоже на то, что это проблема * только *, потому что, если это вызывает вас проблема, сообщение об ошибке будет связано с подзапросом, возвращающим более одного значения. –

+0

Я тоже попробовал JOIN, но он имеет тот же эффект. Как только я использую «UPDATE» в качестве триггера, он дает мне сообщение об ошибке. –

+2

Также добавьте 'SET NOCOUNT ON;' к триггеру. –

ответ

3

Если вы запускаете этот триггер как триггер AFTER UPDATE, он работает рекурсивно, так как он всегда выдает другой оператор UPDATE в той же таблице, что приводит к другому выполнению триггера.

Чтобы обойти это, вам необходимо либо активировать триггер обновления, либо изменить его, если столбец KENNSCHT был изменен. Для последнего можно использовать функцию UPDATE() так:

ALTER TRIGGER [dbo].[kennscht_copy_to_prodverpt_after_update] 
ON [dbo].[Stammdaten] 
AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON 
    IF (UPDATE(KENNSCHT)) 
    BEGIN 
     UPDATE s 
      SET s.PRODVERPT = i.KENNSCHT 
      FROM Stammdaten s 
      INNER JOIN INSERTED i ON i.SNR = s.SNR 
    END 
END 
+2

Рекурсивные триггеры не включены по умолчанию, и если это проблема, они получат предел рекурсии, превышающий ошибку. Ошибка, упомянутая в вопросе, является одной из клиентских инструментов, когда «NOCOUNT ON» не включен. –

+0

Я пробовал это шаг за шагом, но после того, как я установил 'NOCOUNT ON' внутри триггера, он уже работал. –

+1

@Florian Pescka: Тем не менее, я думаю, что было бы неплохо использовать мой код. При необходимости он выдает другое обновление (не всегда, как и исходный код), и оно более надежное, поскольку оно все еще работает, если активируются рекурсивные триггеры. – TToni

Смежные вопросы