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

Sql server 插入多行时在触发器内回滚一行,sql-server,sql-server-2008,triggers,database-trigger,Sql Server,Sql Server 2008,Triggers,Database Trigger,我有一个带有一些列的表“TEST”。“已验证”和“已删除”列是位值 TEST Table: Id VALIDATED DELETED 1 0 0 2 0 0 3 1 0 4 0 0 5 1 0 6 0

我有一个带有一些列的表“TEST”。“已验证”和“已删除”列是位值

 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值和主键

我已为此表和“已删除”列创建了以下触发器,仅在更新时才创建:

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?或者仅对正在处理的行执行回滚


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

摆脱该光标。它什么也不做,只是让事情变得更慢、更复杂。您不需要检查每一行,只需要查看是否有违反业务规则的行正在更新

你的整个触发可以减少到这个

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

摆脱光标。它什么也不做,只是让事情变得更慢、更复杂。您不需要检查每一行,只需要查看是否有违反业务规则的行正在更新

你的整个触发可以减少到这个

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

在上面的触发器中有3个变量,Id、Process\u Id和Process。所以,我不确定这个触发器是否工作。这里不需要光标。您可以将其作为基于集合的查询来执行,而不会产生任何问题。回滚将回滚整个事务,而不是一行。sql server中的触发器每次操作触发一次。@WEI_DBA正确。我已经改正了。打字时出错。对不起,上面的触发器中有3个变量,Id、进程Id和进程。所以,我不确定这个触发器是否工作。这里不需要光标。您可以将其作为基于集合的查询来执行,而不会产生任何问题。回滚将回滚整个事务,而不是一行。sql server中的触发器每次操作触发一次。@WEI_DBA正确。我已经改正了。打字时出错。很抱歉