插入多行时,在触发器内回滚一行

时间:2016-10-28 13:42:39

标签: sql-server sql-server-2008 triggers database-trigger

我有一些表'TEST'包含一些列。列'VALIDATED'和'DELETED'是位值

 TEST Table:
    Id      VALIDATED     DELETED
     1           0          0
     2           0          0
     3           1          0
     4           0          0
     5           1          0
     6           0          0 

Id是INT值和主键。

我为此表创建了以下触发器,并且仅在更新时为“DELETED”列创建了:

CREATE TRIGGER [dbo].[MY_TRIGGER]   
   ON  [dbo].[TEST] 
   FOR UPDATE 
AS 
IF UPDATE([DELETED])
BEGIN

DECLARE @Id INT;

DECLARE db_cursor CURSOR FOR
SELECT DISTINCT (I.Id)
FROM INSERTED I;

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @Id

WHILE @@FETCH_STATUS = 0   
BEGIN  

    IF EXISTS(SELECT * FROM INSERTED WHERE Id = @Id AND VALIDATED = 1)
    BEGIN

        IF EXISTS (SELECT 
                     FROM DELETED D INNER JOIN INSERTED I
                       ON D.Id = I.Id
                    WHERE D.Id = @Id AND D.[DELETED] = 0 
                          AND I.[DELETED] = 1)

        BEGIN
            RAISERROR('CANNOT DELETE!' ,10, 1);
            ROLLBACK
        END
    END


   FETCH NEXT FROM db_cursor INTO @Id
END  

 CLOSE      db_cursor;
 DEALLOCATE db_cursor;
END

现在我执行以下更新声明:

Update TEST
SET    DELETED=1

以上触发器避免将已经验证的行标记为已删除。 当一行被验证并且我试图将其标记为已删除时,则完成回滚。

我怀疑是: 是否正在更新所有行的Roolback?或仅对正在处理的行进行回滚。

如何仅针对引发错误并提交其余内容的行进行回滚?

1 个答案:

答案 0 :(得分:3)

摆脱那个光标。除了使它变得更慢并且比它需要的更复杂之外,它什么都不做。您无需检查每一行,只需查看是否有更新的行违反了您的业务规则。

您的整个触发器可以简化为此。

CREATE TRIGGER [dbo].[MY_TRIGGER]   
   ON  [dbo].[TEST] 
   FOR UPDATE 
AS 
    IF EXISTS 
    (
        SELECT *
        FROM DELETED D 
        INNER JOIN INSERTED I ON D.Id = I.Id
        WHERE D.[DELETED] = 0 
            AND I.[DELETED] = 1
    )
    BEGIN
        RAISERROR('CANNOT DELETE!' ,10, 1);
        ROLLBACK
    END