【问题标题】:Using Merge with Trigger in SQL Server 2012在 SQL Server 2012 中使用合并与触发器
【发布时间】:2018-01-16 12:38:50
【问题描述】:

我面临与合并语句相关的问题我有这样的合并语句

MERGE abc A 
USING xyz B ON A.trans_date = b.trans_date 

WHEN matched AND B.trans_date IS NOT NULL 
   THEN 
       UPDATE 
          SET A.column1 = B.column1, 
              A.column2 = B.column2, 
              A.column3 = B.column3 

WHEN NOT matched BY target AND B.trans_date IS NOT NULL 
   THEN 
      INSERT (column1, column2, column3) 
      VALUES (column1, column2, column3); 

并且像这样在表 ABC 上有一个触发器

ALTER TRIGGER [dbo].[TRG_ABC] 
ON [dbo].[Z_ABC] 
FOR UPDATE 
AS 
    DECLARE @Column4 NUMERIC(9), @Column5 CHAR(1)

    SELECT @Column4 = Column4, @Column5 = Column5 
    FROM inserted 

    UPDATE ABC 
    SET Column5 = CASE 
                     WHEN @Column5 = 'S' 
                        THEN 'Y' 
                        ELSE CASE
                                WHEN @Column5 = 'N' 
                                   THEN 'N' 
                                   ELSE 'U' 
                             END
                  END 
    WHERE Column4 = @Column4

此触发器不适用于更新每一行。更新每一行的代码或任何解决方案有什么问题吗?

【问题讨论】:

    标签: sql sql-server database database-trigger


    【解决方案1】:

    在 Sql Server 中,Trigger 将在语句级别而不是行级别调用。所以Inserted 魔术表将包含所有更新/插入的记录。

    像这样改变触发器

    UPDATE a
    SET    Column5 = CASE
                       WHEN Column5 = 'S' THEN 'Y'
                       WHEN Column5 = 'N' THEN 'N'
                       ELSE 'U'
                     END
    FROM   ABC a
           INNER JOIN inserted i
                   ON i.Column4 = a.Column4 
    

    【讨论】:

      【解决方案2】:

      触发器中的代码应包含基于 SET 的操作

      你已经声明了变量,这将导致只使用最后受影响的行数据

      所以你的内部 UPDATE 会导致错误的结果

      你可以参考merge command in trigger的用法

      【讨论】: