更新多行触发器

时间:2017-02-28 08:18:05

标签: sql sql-server triggers

每当在另一个名为"Candidate_Post_Info_Table_ChangeLogs"的表中更新记录时,我都会尝试在名为"Candidate_Personal_Info_Table"的表中插入数据。每当更新一条记录时我的代码工作正常,但当我尝试更新多行时,它会给出错误:

"子查询返回的值超过1"。

以下是我的代码:

ALTER TRIGGER [dbo].[Candidate_PostInfo_UPDATE]
   ON [dbo].[Candidate_Post_Info_Table]
AFTER UPDATE
AS
BEGIN
   IF @@ROWCOUNT = 0
   RETURN

       DECLARE @Candidate_Post_ID int
       DECLARE @Candidate_ID varchar(50)
       DECLARE @Action VARCHAR(50)
       DECLARE @OldValue VARCHAR(MAX)
       DECLARE @NewValue VARCHAR(MAX)
       DECLARE @Admin_id int

       IF UPDATE(Verified)
       BEGIN
            SET @Action = 'Changed Verification Status'
            SET @Candidate_Post_ID = (Select ID From inserted)
            SET @Candidate_ID = (Select Identity_Number from inserted)
              SET @NewValue = (Select Verified From inserted)
              SET @OldValue = (Select Verified From deleted)
              IF(@NewValue != @OldValue)
              BEGIN
              INSERT INTO  Candidate_Post_Info_Table_ChangeLogs(Candidate_Post_ID, Candidate_ID,  Change_DateTime, action, NewValue, OldValue, Admin_ID)
                VALUES(@Candidate_Post_ID, @Candidate_ID, GETDATE(), @Action,  @NewValue, @OldValue, '1')
                END
       END

END

我已针对此问题搜索了堆栈溢出,但无法获得特定于此方案的任何相关答案。

2 个答案:

答案 0 :(得分:1)

当您将多行插入/更新到表中时,系统使用的Inserted临时表包含已插入或更新的所有行中的所有值。

因此,如果对6行进行更新,Inserted表也将有6行,并执行以下操作:

SET @Candidate_Post_ID = (Select ID From inserted)

将返回错误,与执行此操作相同:

SET @Candidate_Post_ID = (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6)

从事物的外观来看,你试图用迭代的方法做到这一点。基于集合更好。也许可以考虑在TRIGGER的主体中这样做(没有所有参数......):

IF UPDATE(Verified)
BEGIN
    INSERT INTO Candidate_Post_Info_Table_ChangeLogs 
    (
         Candidate_Post_ID
        ,Candidate_ID
        ,Change_DateTime
        ,action
        ,NewValue
        ,OldValue
        ,Admin_ID
    )
    SELECT 
         I.ID
        ,I.Identity_Number
        ,GETDATE()
        ,'Changed Verification Status'
        ,I.Verified
        ,O.Verified
        ,'1'
    FROM Inserted I
    INNER JOIN Deleted O
        ON I.ID = O.ID -- Check this condition to make sure it's a unique join per row
    WHERE I.Verified <> O.Verified
END

答案 1 :(得分:0)

使用游标在以下主题中解决了类似案例....请检查

SQL Server A trigger to work on multiple row inserts

此外,以下主题提供了基于 set 的方法

的解决方案

SQL Server - Rewrite trigger to avoid cursor based approach

*以上两个线程都来自堆栈溢出...