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表中没有数据