开发者

What comparison method is better?

开发者 https://www.devze.com 2023-01-18 13:59 出处:网络
I have a trigger in a table with a good number of columns (perhaps around 100) and quite a lot of updates (for some definition of \"a lot of\").

I have a trigger in a table with a good number of columns (perhaps around 100) and quite a lot of updates (for some definition of "a lot of"). If any of some fields have changed, the trigger inserts some data in another table.

For obvious reasons, I want this trigger to run as fast as possible. What's the best method to do the comparison? For now I have those:

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) <> (S开发者_运维百科ELECT Fld6 FROM Deleted) OR
    (SELECT Fld7 FROM Inserted) <> (SELECT Fld7 FROM Deleted))
THEN...

I would usually prefer the first method, as it's more compact and seems more idiomatic. However, when speed is an issue, how should I do it?


The second version is completely broken for multi-row UPDATES, so for that reason alone, I'd do a variant of the first:

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

Assuming the PK is stable and unchanging


Why don't you test your changing columns by using IF UPDATE(Column1,Column2,...) That will let you know whether any of the columns have changed that you're interested in. See http://msdn.microsoft.com/en-us/library/ms187326.aspx for details on the UPDATE() function.

You'll also be able to use it if the PK has been modified, whereas comparing between the inserted and deleted the way you're trying to go about it will miss out on changes to the PK.

The solution involving testing the inequality of all of the fields will fail unless you SET ANSI_NULLS OFF before comparing.

For example:

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

Of course, you could put in additional tests rather than going with the ansi_nulls option, but that gets particularly crazy if you're doing this with many fields. Also: you must set ansi_nulls off prior to creating the trigger - you can't turn it on and off inside the trigger, so the whole thing must have the same ansi_nulls setting.

0

精彩评论

暂无评论...
验证码 换一张
取 消