【问题标题】:Check if only a specific column was updated in a sql server trigger?检查是否仅在 sql server 触发器中更新了特定列?
【发布时间】:2015-10-21 17:12:51
【问题描述】:

我想编写一个触发器来执行一些逻辑,除非只更新了一个特定的列,例如如果仅更新了“UpdateDate”列,则不必费心触发触发器。

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

【问题讨论】:

    标签: sql-server triggers


    【解决方案1】:

    对于 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;
    

    这种方法的优势在于,它不仅能正确判断列是否已更新,还能正确判断数据是否真的更改了,这通常是您所关心的。

    【讨论】:

    • 这很好用,但您可以跳过临时表并挤出一点性能。当您只关心它们是否存在时,将所有行写入临时表是没有意义的。只需将 EXCEPT 查询作为 EXISTS 的条件即可。
    • @SeanLange 当然 - 我从触发器中复制了这段代码,稍后我对更改的行进行了处理,但你的观点是有效的。
    • 我可以看到如果这就是您所追求的,这将很有用,但是如果您对表中的所有其他列使用UPDATE(),这会遇到同样的问题:如果有人添加了另一列并且不修改它会中断的触发器。
    【解决方案2】:

    我最终想出了这个逻辑:

    如果

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

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

    例如

    -- 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 
    

    【讨论】:

    • 请注意,这种方法可能会导致在更新列时触发触发器,但实际上并未更改值。请参阅我的答案以了解另一种方法。
    • 我同意。就我而言,我不在乎列是否更新为相同的值,但绝对值得牢记,因为人们经常会关心这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多