【问题标题】:Check if inserted and deleted tables are identical in SQL Server trigger检查 SQL Server 触发器中插入和删除的表是否相同
【发布时间】:2017-09-15 16:02:28
【问题描述】:

我编写了一个触发器来将更新历史记录保存在一个表中。它运作良好。但是,我注意到有时该表会使用相同的确切值进行更新。这实际上不会更改表,但会触发触发器,从而导致我的历史表中出现重复的行。

为了解决这个问题,我只想在inserteddeleted 表不相同时执行触发器主体。

这是我当前的触发器。它由一个 MERGE 和一个 INSERT 组成。如果inserteddeleted 表相同,我不想合并或插入:

BEGIN
    DECLARE @yesterday date, @maxDate date
    SET @yesterday = DATEADD(DD, -1, GETDATE())
    SET @maxDate = '9999-12-31'

    MERGE dbo.tblHistory AS Target
    USING (SELECT * FROM inserted) AS Source 
       ON (Target.ID = Source.ID AND Target.EndDate = @maxDate)

    WHEN MATCHED AND Target.StartDate > @yesterday THEN
        DELETE

    WHEN MATCHED THEN
        UPDATE 
            SET Target.EndDate = @yesterday
    ;

    --Insert updated row into History here
END

这似乎是最适合人类阅读和合乎逻辑的方式。但是我不确定它是否最有效。

【问题讨论】:

  • 这个触发器只有for update吗?还是它处理更新、删除和插入?
  • 不相关:USING (SELECT * FROM inserted) AS Source 可以缩短为USING Inserted AS Source
  • @ShannonSeverance 仅更新

标签: sql sql-server tsql merge


【解决方案1】:

您可以使用下面的 except 运算符进行检查

  ;with cte
   as
   (SELECT * FROM inserted
    EXCEPT
    SELECT * FROM deleted
    union all
   SELECT * FROM deleted
    EXCEPT
    SELECT * FROM inserted
   )
select * from cte

if @@rowcount>0
begin
--rest of your query
end

【讨论】:

  • 但是你会将结果集返回给客户端?不是吗?如果是,则需要一些环绕 EXCEPT。
  • 我不能 100% 确定用户是在向客户端返回结果还是只是在做一些处理
  • 我没有返回结果集。目前正在测试此解决方案。不过我需要做一些小改动。
  • 此代码将无法正常工作:SELECT * FROM (VALUES (1), (2)) x(a) EXCEPT SELECT * FROM (VALUES (1), (2), (3)) x(a)
  • @TheGameiswar,但我认为最好使用 count(*) 和变量
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 2010-12-17
相关资源
最近更新 更多