插入多行时在触发器内回滚一行
Rollback within trigger for one row when multiple rows are in inserted
我有一个包含一些列的 table '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 值和主键。
我仅在更新时为此 table 和列 '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
以上触发器避免将已验证的行标记为已删除。
当一行被验证并且我试图将其标记为已删除时,回滚就完成了。
我的疑问是:
是否对所有更新的行进行了回滚?或者仅对正在处理的行进行回滚。
如何只回滚引发错误的行并提交其余行?
去掉那个光标。它什么也没做,只是让这个过程变得比它需要的更慢和更复杂。您不需要检查每一行,您只需要查看是否有违反您的业务规则的正在更新的行。
你的整个触发器可以减少到这个。
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
我有一个包含一些列的 table '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 值和主键。
我仅在更新时为此 table 和列 '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
以上触发器避免将已验证的行标记为已删除。 当一行被验证并且我试图将其标记为已删除时,回滚就完成了。
我的疑问是: 是否对所有更新的行进行了回滚?或者仅对正在处理的行进行回滚。
如何只回滚引发错误的行并提交其余行?
去掉那个光标。它什么也没做,只是让这个过程变得比它需要的更慢和更复杂。您不需要检查每一行,您只需要查看是否有违反您的业务规则的正在更新的行。
你的整个触发器可以减少到这个。
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