我编写了一个触发器,需要根据实际更新的行中的哪些列对表执行一些不同的工作。我用
完成了这个IF UPDATE(column-name)
那部分工作正常。然而,事实证明,代码的其他部分通过设置每个值来更新行,无论值是否实际更改,这会导致触发器触发“已更新”但其值实际上未更改的部分一点都不
由于更改导致此问题的代码可能不是一个选项,除了必须在INSERTED和DELETED表之间进行比较之外,还有一种更简单的方法可以防止这种情况(在这种情况下,IF UPDATE是没有意义的)吗?
答案 0 :(得分:14)
IF EXISTS (SELECT *
FROM
INSERTED I JOIN DELETED D ON I.Key = D.Key
WHERE
I.Col <> D.Col)
...
或使用表变量进行缓存,以避免重复使用I和D.
SELECT
CASE WHEN I.Col1 <> D.Col1 THEN 1 ELSE 0 END AS Col1Diff,
CASE WHEN I.Col2 <> D.Col2 THEN 1 ELSE 0 END AS Col2Diff,
...
FROM
INSERTED I JOIN DELETED D ON I.Key = D.Key
或组合想法以预先测试所有更改并退出触发器
答案 1 :(得分:7)
正如其他人所说,你必须使用INSERTED
和DELETED
表。
这是我所做的,而不是:
IF UPDATE(col1) OR UPDATE(col2))
UPDATE table1
SET col3 = 1
FROM INSERTED
WHERE table1.Id = INSERTED.Id
我做了:
IF UPDATE(col1) OR UPDATE(col2))
UPDATE table1
SET col3 = 1
FROM
(SELECT Id, col1, col2 FROM INSERTED
EXCEPT
SELECT Id, col1, col2 FROM DELETED) AS ALTERED
WHERE table1.Id = ALTERED.Id
使用EXCEPT
选择我感兴趣的列不存在于删除(或原始数据)表中的不同行(意味着这些列的值已更改)。我不知道这是否是最好的答案,但似乎确实有效。
答案 2 :(得分:4)
该列已更新。旧值和新值相同只是一个细节。我认为你唯一的解决方案是比较插入和删除的伪表之间的值。
答案 3 :(得分:2)
不是我知道的。 INSERTED
和DELETED
是有原因的,相比它们似乎是我的最佳选择。
IF UPDATE()
只是告诉您是否插入或更新尝试,甚至不反映该尝试是否成功。