触发器学习

After 触发器将在处理触发操作(Insert、Update 或 Delete)、Instead Of 触发器和约束之后激发。Instead Of是将在处理约束前激发,以替代触发操作。

After触发器在触发时操作已影响表中数据,Instead of 触发器触发时操作未影响数据表中数据。

不存在DDL 类型的Instead of 触发器,在DDL触发器创建时可以使用Instead表和Deleted表,但是会引发运行时异常。

可以在存储过程或触发器中执行 ROLLBACK TRANSACTION 或 COMMIT TRANSACTION Transact-SQL 语句,但这样可能会导致错误。(MSDN)

应该在触发器中尽量避免事务会滚操作,测试如下:

复制代码
--创建测试环境
USE tempdb
GO
CREATE TABLE dbo.TRTest
(
ID INT
)
GO
CREATE TABLE dbo.TRTestHistory
(
ID INT,
InsertDate datetime default GETDATE()
);
复制代码
复制代码
-- 创建INSTEAD OF 触发器
--
第一次向dbo.TRTestHistory插入数据,然后回滚事务
--
第二次向dbo.TRTestHistory插入数据,然后提交事务
CREATE TRIGGER TR_TRTest ON dbo.TRTest
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRAN
Insert into dbo.TRTestHistory(ID)
SELECT ID FROM inserted
ROLLBACK TRAN

BEGIN TRAN
Insert into dbo.TRTestHistory(ID)
SELECT ID+100 FROM inserted
COMMIT TRAN
END
--清理表中数据
TRUNCATE TABLE dbo.TRTest
TRUNCATE TABLE dbo.TRTestHistory

--尝试插入数据,触发TR_TRTest触发器
INSERT INTO dbo.TRTest
SELECT 1

--检查数据表中数据
SELECT * FROM dbo.TRTest
SELECT * FROM dbo.TRTestHistory
结果:插入操作提示错误“The transaction ended in the trigger. The batch has been aborted.”,但dbo.TRTestHistory表中有数据插入。
 
复制代码
复制代码
-- 创建INSTEAD OF 触发器
--
第一次向dbo.TRTestHistory插入数据,然后回滚事务
--
第二次向dbo.TRTestHistory插入数据,然后提交事务
ALTER TRIGGER TR_TRTest ON dbo.TRTest
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRAN TR1
Insert into dbo.TRTestHistory(ID)
SELECT ID FROM inserted
ROLLBACK TRAN TR2

BEGIN TRAN
Insert into dbo.TRTestHistory(ID)
SELECT ID+100 FROM inserted
COMMIT TRAN
END
--清理表中数据
TRUNCATE TABLE dbo.TRTest
TRUNCATE TABLE dbo.TRTestHistory

--尝试插入数据,触发TR_TRTest触发器
INSERT INTO dbo.TRTest
SELECT 1

--检查数据表中数据
SELECT * FROM dbo.TRTest
SELECT * FROM dbo.TRTestHistory
结果:插入时异常“Cannot roll back TR1. No transaction or savepoint of that name was found. The statement has been terminated. ”,
但dbo.TRTestHistory表中没有数据
复制代码
复制代码
-- 创建AFTER触发器
--
第一次向dbo.TRTestHistory插入数据,然后回滚事务
--
第二次向dbo.TRTestHistory插入数据,然后提交事务
ALTER TRIGGER TR_TRTest ON dbo.TRTest
AFTER INSERT
AS
BEGIN
BEGIN TRAN TR1
Insert into dbo.TRTestHistory(ID)
SELECT ID FROM inserted
ROLLBACK TRAN TR1

BEGIN TRAN
Insert into dbo.TRTestHistory(ID)
SELECT ID+100 FROM inserted
COMMIT TRAN
END
--清理表中数据
TRUNCATE TABLE dbo.TRTest
TRUNCATE TABLE dbo.TRTestHistory

--尝试插入数据,触发TR_TRTest触发器
INSERT INTO dbo.TRTest
SELECT 1

--检查数据表中数据
SELECT * FROM dbo.TRTest
SELECT * FROM dbo.TRTestHistory
结果:插入时异常“Cannot roll back TR1. No transaction or savepoint of that name was found. The statement has been terminated. ”,
但dbo.TRTestHistory表中没有数据
复制代码



总结:大部分情况下在触发器中使用ROLLBACK TRAN会导致包括触发器内部以及引发触发器激活的操作在内的事务会滚,但部分情况下触发器ROLLBACK TRAN后续的操作仍能操作成功。

 

 

 

 

posted on   笑东风  阅读(2038)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现

导航

点击右上角即可分享
微信分享提示