TSql Trigger只需要在值已更改的列上触发

Rya*_*ins 9 t-sql sql-server triggers

我写了一个触发器,需要根据实际更新的行中的哪些列对表执行一些不同的工作.我完成了这个

IF UPDATE(column-name)
Run Code Online (Sandbox Code Playgroud)

那部分工作正常.然而,事实证明,代码的其他部分通过设置每个值来更新行,无论值是否实际更改,这会导致触发器触发"已更新"但其值实际上未更改的部分一点都不

由于更改导致此问题的代码可能不是一个选项,除了必须在INSERTED和DELETED表之间进行比较之外,是否有更简单的方法来防止这种情况(在这种情况下,IF UPDATE是没有意义的)?

gbn*_*gbn 14

IF EXISTS (SELECT *
          FROM
             INSERTED I JOIN DELETED D ON I.Key = D.Key
          WHERE
             I.Col <> D.Col)
...
Run Code Online (Sandbox Code Playgroud)

或使用表变量进行缓存,以避免重复使用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
Run Code Online (Sandbox Code Playgroud)

或者结合创意来预先测试所有变化并退出触发器


Rya*_*ins 7

正如其他人所说,你必须使用INSERTEDDELETED表.

这是我所做的,而不是:

IF UPDATE(col1) OR UPDATE(col2))
UPDATE table1
SET col3 = 1
FROM INSERTED
WHERE table1.Id = INSERTED.Id
Run Code Online (Sandbox Code Playgroud)

我已经做好了:

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
Run Code Online (Sandbox Code Playgroud)

使用EXCEPT选择在我删除的(或原始数据)表中不存在我感兴趣的列的不同行(意味着这些列的值已更改).我不知道这是否是最佳答案,但似乎确实有效.