什么比较方法更好?

时间:2010-10-01 10:00:13

标签: sql-server tsql optimization triggers

我在一个包含大量列(可能大约100个)的表中有一个触发器和相当多的更新(对于“很多”的某些定义)。 如果某些字段已更改,则触发器会在另一个表中插入一些数据。

出于显而易见的原因,我希望此触发器尽可能快地运行。进行比较的最佳方法是什么? 现在我有那些:

IF NOT EXISTS (SELECT * FROM Inserted i, Deleted d WHERE 
    i.Fld1 = d.Fld1 AND i.Fld2 = d.Fld2 AND
    i.Fld3 = d.Fld3 AND i.Fld4 = d.Fld4 AND
    i.Fld5 = d.Fld5 AND i.Fld6 = d.Fld6 AND
    i.Fld7 = d.Fld7)     
    THEN ...

IF ((SELECT Fld1 FROM Inserted) <> (SELECT Fld1 FROM Deleted) OR
    (SELECT Fld2 FROM Inserted) <> (SELECT Fld2 FROM Deleted) OR
    (SELECT Fld3 FROM Inserted) <> (SELECT Fld3 FROM Deleted) OR
    (SELECT Fld4 FROM Inserted) <> (SELECT Fld4 FROM Deleted) OR
    (SELECT Fld5 FROM Inserted) <> (SELECT Fld5 FROM Deleted) OR
    (SELECT Fld6 FROM Inserted) <> (SELECT Fld6 FROM Deleted) OR
    (SELECT Fld7 FROM Inserted) <> (SELECT Fld7 FROM Deleted))
THEN...

我通常更喜欢第一种方法,因为它更紧凑,看起来更惯用。但是,当速度成为问题时,我该怎么办?

2 个答案:

答案 0 :(得分:1)

对于多行更新,第二个版本完全被破坏,所以仅仅因为这个原因,我会做第一个版本的变体:

INSERT INTO ANotherTable (Column1, COlumn2, /* Etc */)
SELECT i.Column1,d.Column1, /* Other COlumns */
FROM
    inserted i
        inner join
    deleted d
        on
            i.Fld1 = d.Fld1 and /* For each column in PK */
            i.Fld2 <> d.Fld2 /* For each non-PK column */

假设PK稳定且不变

答案 1 :(得分:-1)

为什么不使用IF UPDATE(Column1,Column2,...)测试更改的列,这会让您知道您感兴趣的列是否已更改。有关http://msdn.microsoft.com/en-us/library/ms187326.aspx的详细信息,请参阅{{3}} 1}}功能。

如果PK已被修改,您也可以使用它,而在UPDATE()inserted之间进行比较,您尝试进行的方式将会错过PK。

除非您在比较之前deleted,否则涉及测试所有字段不等式的解决方案将失败。

例如:

SET ANSI_NULLS OFF

当然,您可以进行额外的测试,而不是使用create table table1 ( a varchar(4), b varchar(4) null) create table table2 ( a varchar(4), b varchar(4) null) go insert into table1 ( a, b ) select 'asdf', null insert into table2 ( a, b ) select 'asdf', 'zzzz' --Expect no results select * from table1 inner join table2 on a.a = b.a where a.b <> b.b set ansi_nulls off --Expect 1 result select * from table1 inner join table2 on a.a = b.a where a.b <> b.b 选项,但如果您使用多个字段执行此操作,则会特别疯狂。另外:在创建触发器之前必须ansi_nulls - 您无法在触发器内打开和关闭它,因此整个事件必须具有相同的set ansi_nulls off设置。