sql-server – 最有效的方法来检测MS SQL Server中的列更改

我们的系统在SQL Server 2000上运行,我们正在准备升级到SQL Server 2008.我们有很多触发代码,我们需要检测给定列中的更改,然后在该列上操作已经改变。

显然,SQL Server提供了UPDATE()COLUMNS_UPDATED()功能,但这些功能只告诉您哪些列涉及SQL语句,哪些列实际上已经更改。

要确定哪些列已更改,您需要与以下代码相似的代码(对于支持NULL的列):

IF UPDATE(Col1)
    SELECT @col1_changed = COUNT(*) 
    FROM Inserted i
        INNER JOIN Deleted d ON i.Table_ID = d.Table_ID
    WHERE ISNULL(i.Col1, '<unique null value>') 
            != ISNULL(i.Col1, '<unique null value>')

对于您有兴趣测试的每一列,都需要重复此代码。然后,您可以检查“更改”值以确定是否执行昂贵的操作。当然,这个代码本身也是有问题的,因为它只告诉你列中的至少一个值已经改变了所有被修改的行。

您可以使用以下内容测试单个UPDATE语句:

UPDATE Table SET Col1 = CASE WHEN i.Col1 = d.Col1 
          THEN Col1 
          ELSE dbo.fnTransform(Col1) END
FROM Inserted i
    INNER JOIN Deleted d ON i.Table_ID = d.Table_ID

…但是当您需要调用存储过程时,这不能正常工作。在这些情况下,您必须回到其他方法,就我所知。

我的问题是,任何人是否有洞察力(或更好的是硬数据),关于在触发器中预测数据库操作的最佳/最便宜的方法是否实际改变了修改行中的特定列值,不。上述两种方法都不是理想的,我想知道是否存在更好的方法。

让我们开始,我永远不会,我的意思是从来没有在触发器中调用存储过程。要考虑多行插入,你必须通过proc来游标。这意味着您通过基于集合的查询(比如更新所有价格10%)加载的20万行可能会很好地锁定该表数小时,因为触发器尝试勇敢地处理负载。此外,如果在proc中发生变化,您可以将表中的任何插入物完全挂断,甚至完全挂断桌子。我是一个坚定的beliver,触发器代码应该在触发器之外不应该调用任何其他内容。

我个人喜欢简单地做我的任务。如果我已经写了我想在触发器中正确执行的操作,它将仅更新,删除或插入列已更改的位置。

示例:假设要更新您存储在两个位置的last_name字段,因为出于性能原因,将其放置在那里。

update t
set lname = i.lname
from table2 t 
join inserted i on t.fkfield = i.pkfield
where t.lname <>i.lname

正如你所看到的,它只会更新与我正在更新的表中当前不同的lnames。

如果你想做审计,只记录那些改变的行,然后使用所有字段进行比较
    其中i.field1 d.field1或i.field2 d.field3(所有字段等)

http://stackoverflow.com/questions/651524/most-efficient-method-to-detect-column-change-in-ms-sql-server

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:sql-server – 最有效的方法来检测MS SQL Server中的列更改