在Update Trigger
中获取所有已修改字段的列表的最简单方法是什么?
我能想到的最紧凑的方法是做某种类型的事情:
IF EXISTS(SELECT 1 FROM INSERTED INNER JOIN DELETED ON INSERTED.[FIELD_TO_CHECK] = DELETE.[FIELD_TO_CHECK])
但这将意味着我必须对要检查的每个字段执行此操作。我希望使用cursor
包含有关所有已修改字段的信息的方法。
(不需要进行大量更新,INSERTED
或DELETED
中不需要多于1条记录)
我添加了一个if语句来忽略大量更新,因为它们属于不同的类别。
答案 0 :(得分:1)
不幸的是,我不知道有任何可靠的内置函数可以为您提供指示,当更新语句触发触发器时,列的值是否实际发生了变化。
但是,您可以执行一个非常简单的select语句来查看哪些值在哪些行中发生了变化:
SELECT IIF(ISNULL(NULLIF(I.Col, D.Col), NULLIF(D.Col, I.Col)) IS NULL, 0, 1) As Col_Updated
FROM Inserted I
JOIN Deleted D
ON I.PrimaryKey = D.PrimaryKey
如果两列相等,则NULLIF
函数将返回null
。如果不是,则返回第一列的值。
ISNULL
函数将返回不是null
的第一个参数,如果两个参数都为null,则返回null
。
在两个ISNULL
函数的结果上使用NULLIF
时,如果两个列的值相同,即使它们都为null,它们的列值也将相反。如果值不同,则即使其中一个为null而另一个不是,则null
将返回一个值。因此,您要做的就是检查ISNULL
是否返回值或为null-如果返回ISNULL
,则表明该列的值未更改。如果返回值,则将其更改。
当然,对于不可为空的列,您可以简化如下条件:
null
但是我建议反对,因为如果有人将列更改为允许null,则触发代码将不得不更改以支持该操作-以我的经验,这是一个等待发生的错误-触发代码可能不会更改,从而导致假阴性。
You can see a live demo on rextester.
更新
您可以使用的另一种简单方法是:
SELECT IIF(I.Col <> D.Col, 1, 0) As Col_Updated
FROM...
此方法依赖于这样的事实:将null与其他任何内容进行比较都会得到IIF((I.Col IS NULL AND D.Col IS NULL) OR (I.Col = D.Col), 0, 1) as IsUpdated.
,该结果基本上等同于unknown
。
恕我直言,这更具可读性。