触发器学习

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后续的操作仍能操作成功。

 

 

 

 

版权声明:本文为TeyGao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/TeyGao/archive/2012/01/31/2333878.html