什么比较方法比较好?

发布于 2024-09-25 20:22:41 字数 986 浏览 1 评论 0原文

我的表中有一个触发器,其中有大量列(可能大约 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...

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

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) <> (SELECT 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难理解 2024-10-02 20:22:41

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

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 是稳定且不变的

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

虫児飞 2024-10-02 20:22:41

为什么不使用 IF UPDATE(Column1,Column2,...) 测试更改的列,这会让您知道您感兴趣的列是否已更改。请参阅 < a href="http://msdn.microsoft.com/en-us/library/ms187326.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/ms187326.aspx< /a> 有关 UPDATE() 函数的详细信息。

如果 PK 已被修改,您也可以使用它,而在插入删除之间进行比较时,您尝试执行的方式将会错过关于PK的改动。

除非您在比较之前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 选项,但如果您对许多字段执行此操作,情况会变得特别疯狂。另外:您必须在创建触发器之前设置 ansi_nulls off - 您无法在触发器内打开和关闭它,因此整个事物必须具有相同的 ansi_nulls 设置。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文