Вам нужно написать запрос, который работает с множествами , а не пытаться делать что-то процедурно. inserted
и deleted
- это псевдо-таблицы, содержащие столько строк, сколько было затронуто операцией, вызвавшей срабатывание триггера. Это может быть легко больше чем 1 . Кроме того, UPDATE()
отвечает на вопрос, отличный от того, что, я думаю, вы пытаетесь задать (он просто эффективно сообщает, упоминался ли этот столбец в предложении SET
, а не изменилось ли значение).
Итак, я бы написал что-то вроде:
create TRIGGER [dbo].[trg_DocTypeChangeTracking] ON [dbo].[master]
AFTER UPDATE
AS
declare @MasKey int;
declare @DocType varchar(100);
SET NOCOUNT ON
INSERT dbo.tblDocTypeChangeTracking
(
MasKey,
DocType,
DateModified
)
SELECT
i.mas_key,
DocType,
GETDATE()
from
inserted i
inner join
deleted d
on
i.mas_key = d.mas_key
cross join
(values(1,'Passport'), (2,'Residency')) t(ID,DocType)
where
(t.ID = 1 and i.passp_isu != d.passp_isu) or
(t.ID = 2 and i.res_isu != d.res_isu)
Вы также заметите, что если, скажем, и passp_isu
, и res_isu
изменились в какой-либо конкретной строке, мы создаем две строки для вставки в tblDocTypeChangeTracking
.
Теперь вышесказанное является неполным по двум причинам. Во-первых, я еще не перечислил все условия для каждого DocType
или для каждого DocType
- я оставляю это как упражнение для вас. Кроме того, я предположил, что passp_isu
и т. Д. Не обнуляются и / или нам не нужно обнаруживать null
-> not null
изменений (и наоборот). В стандартном SQL я мог бы написать i.passp_isu is different from d.passp_isu
, чтобы выполнить проверку различий "null
". К сожалению, в SQL Server это еще не поддерживается, поэтому, если вам нужно поддерживать такие проверки, вам нужно записать каждое сравнение как:
(i.passp_isu != d.passp_isu or
i.passp_isu is null and d.passp_isu is not null or
i.passp_isu is not null and d.passp_isu is null)
Что гораздо менее красиво.