我在一个包含大量列(可能大约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...
我通常更喜欢第一种方法,因为它更紧凑,看起来更惯用。但是,当速度成为问题时,我该怎么办?
答案 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
设置。