Какой метод сравнения лучше? - PullRequest
0 голосов
/ 01 октября 2010

У меня есть триггер в таблице с большим количеством столбцов (возможно, около 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 ]

1 голос
/ 01 октября 2010

Вторая версия полностью не работает для многострочных ОБНОВЛЕНИЙ, поэтому по одной этой причине я бы сделал вариант первой:

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

Предполагая, что ПК стабильный и неизменный

0 голосов
/ 01 октября 2010

Почему бы вам не протестировать изменяющиеся столбцы с помощью IF UPDATE(Column1,Column2,...) Это позволит вам узнать, изменился ли какой-либо из интересующих вас столбцов. См. http://msdn.microsoft.com/en-us/library/ms187326.aspx для получения подробной информации о UPDATE()function.

Вы также сможете использовать его, если PK был изменен, тогда как сравнение между inserted и 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 до создания триггера - вы не можете включать и выключать его внутри триггера, поэтому все это должно иметь одинаковую настройку ansi_nulls.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...