我有一些表'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?或仅对正在处理的行进行回滚。
如何仅针对引发错误并提交其余内容的行进行回滚?
答案 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