检查sql server触发器中是否只更新了特定列?

时间:2015-10-21 17:12:52

标签: sql-server triggers

我想写一个触发器来执行某些逻辑,除非只更新了一个特定的列,例如如果仅更新了'UpdateDate'列,则不要打扰触发器。

我知道我可以使用UPDATE()COLUMNS_UPDATED(),但似乎很难以可维护的方式编写它以检查是否只更新了一列。例如。我可以对表中的每个其他列调用UPDATE(),但如果有人添加了另一列而没有修改触发器,它将会中断。

2 个答案:

答案 0 :(得分:2)

对于SQL Server 2005+,我会这样做:

假设Column4是您要忽略的特定列,我会这样做:

select *
into #changedRows
from (
   select Column1, Column2, Column3 from deleted 
   except 
   select Column1, Column2, Column3 from inserted
) x

if not exists (select * from #changedRows)
   return;

这种方法的优点在于,它不仅可以正确地确定列是否已更新,还可以正确确定数据是否实际已更改,这通常是您所关心的。

答案 1 :(得分:1)

我最终提出了这个逻辑:

如果

  • 感兴趣的列已更新,
  • COLUMNS_UPDATED()只有一位设置

然后不要触发其余的触发器。

e.g。

-- If columns_updated() is bigger than a bigint will take then 
-- just continue. We could deal with this better but not an issue for me.
if datalength(columns_updated())<63 begin 

    declare @colsUpdated bigint
    set @colsUpdated = cast( columns_updated() as bigint ) 

    -- if UpdateDate column was updated AND there was only a single column updated 
    -- don't run the rest of the trigger. See http://stackoverflow.com/a/4624295/8479
    -- for discussion of how to check if only one bit of a number is set. If only 
    -- one bit is set then only one col was updated, and we use update() to check 
    -- if it was UpdateDate.
    if update(UpdateDate) 
        and ( @colsUpdated & ( @colsUpdated-1 ) = 0 )
    begin 

        return;
    end 
end