sql-server - ROLLBACK 使 INSERTED 表中的数据在 AFTER INSERT TRIGGER 中删除
问题描述
我举一个例子来说明我的问题。我创建了一个这样的表:
CREATE TABLE a
(
id INT
)
然后我创建了一个AFTER INSERT
触发器,不允许插入id = 1
到表中a
:
CREATE TRIGGER [dbo].[insert_a]
ON [dbo].[a] AFTER INSERT
AS
BEGIN
DECLARE @id INT
SELECT @id = id FROM inserted
IF @id = 1
BEGIN
RAISERROR('1', 12, 1)
ROLLBACK;
END
SELECT * FROM inserted
END
然后我插入id = 1
表a
:
INSERT INTO a VALUES(1)
我从桌子上什么也得不到INSERTED
。
我意识到当我 ROLLBACK 然后 + 表中的数据a
被回滚(我知道)并且INSERTED
表中的数据也被删除。这是为什么?
如果我将AFTER INSERT
触发器更改为INSTEAD OF INSERT
触发器:
ALTER TRIGGER [dbo].[insert_a]
ON [dbo].[a] INSTEAD OF INSERT
AS
BEGIN
DECLARE @id INT
SELECT @id = id FROM inserted
IF @id = 1
BEGIN
RAISERROR('1', 12, 1)
ROLLBACK
END
SELECT * FROM inserted
END
INSERT INTO a VALUES(1)
然后我得到结果:
id
1
这意味着INSERTED
表中的数据虽然已回滚,但不会被删除。
帮我深入解释一下触发器内部发生了什么?
解决方案
据我所知,这是预期的行为。只是 AFTER 可能有点误导,具体取决于您如何看待它。
“触发器和触发它的语句被视为单个事务,可以从触发器内部回滚。如果检测到严重错误,则整个事务会自动回滚。”。
推荐阅读
- git - git 功能、发布和修补程序有什么区别?
- android - 如何在firebase android中存储数据
- c# - UWP 复杂文本块前景
- hyperledger-fabric - 在 BYFN for Hyperledger - Fabric 中,如果我们只想通过重命名 org1 名称来运行 byfn,我们需要更新哪些文件来更新 Org 的名称
- angular6 - 如何使用角度 6 中的反应形式验证复选框
- apache-kafka - SpringBoot中的Kafka分区
- javascript - 测试字符串是否匹配正则表达式和包含斜杠的变量
- xml - 在嵌套上下文中使用 position() 的 XPath 不会产生所需的结果
- java - Java 8 Young gc 耗时超过 1s,如何减少新生代 gc 时间
- node.js - 如何在 TypeScript 中注释“require express()”返回的实体?