代码之家  ›  专栏  ›  技术社区  ›  raven

什么比较法比较好?

  •  0
  • raven  · 技术社区  · 15 年前

    我在一个表中有一个触发器,其中有大量的列(可能大约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 回复  |  直到 15 年前
        1
  •  1
  •   Damien_The_Unbeliever    15 年前

    第二个版本对于多行更新是完全中断的,因此仅出于这个原因,我将做第一个版本的一个变体:

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

        2
  •  -1
  •   David T. Macknet    15 年前

    为什么不使用 IF UPDATE(Column1,Column2,...) 这将让您知道是否有任何列发生了您感兴趣的更改。见 http://msdn.microsoft.com/en-us/library/ms187326.aspx 有关 UPDATE() 功能。

    如果pk已被修改,您也可以使用它,而比较 inserted deleted 您尝试的方式将错过对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 选项,但是如果你在很多领域都这样做的话,那就特别疯狂了。还有:你必须 set ansi_nulls off 在创建触发器之前-您不能在触发器内部打开和关闭它,因此整个事件必须具有相同的 小茴香 设置。