1.系统在默认情况下:
BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , 9999999999999999999 ,--字段类型是int,但9999999999999999999超过int的最大值,会溢出报错 N'测试自动回滚' ); UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚'; COMMIT TRAN;
执行消息:
消息 8115,级别 16,状态 2,第 3 行
将 expression 转换为数据类型 int 时出现算术溢出错误。
语句已终止。
(54 行受影响)
可以看出:Insert语句报错后,系统继续执行后面的Update语句(有行数受影响),没有回滚事务
BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , ,--此处有语法错误 N'测试自动回滚' ); UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚1'; COMMIT TRAN;
执行消息:
消息 102,级别 15,状态 1,第 13 行
“,”附近有语法错误。
可以看出:Insert语句报错后,并没有继续执行Update语句,事务直接回滚。
2.SET XACT_ABORT { ON | OFF } :
SQL ServerTransact-SQL,参照https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-xact-abort-transact-sql?view=sql-server-2017
(1)为ON时,会自动回滚当前事务,举例如下:
SET XACT_ABORT ON BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , 9999999999999999999 ,--字段类型是int,但9999999999999999999超过int的最大值,会溢出报错 N'测试自动回滚' ); UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚'; COMMIT TRAN;
执行消息:
消息 8115,级别 16,状态 2,第 4 行
将 expression 转换为数据类型 int 时出现算术溢出错误。
可以看出:Insert语句报错后,并没有继续执行Update语句,事务直接回滚
(2)为OFF时,不会自动回滚当前事务,会继续执行报错后面的语句,举例如下:
SET XACT_ABORT OFF BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , 9999999999999999999 ,--字段类型是int,但9999999999999999999超过int的最大值,会溢出报错 N'测试自动回滚' ); UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚'; COMMIT TRAN;
执行消息:
消息 8115,级别 16,状态 2,第 4 行
将 expression 转换为数据类型 int 时出现算术溢出错误。
语句已终止。
(54 行受影响)
可以看出:Insert语句报错后,系统继续执行后面的Update语句(有行数受影响),没有回滚事务
(3)注意点:
SET XACT_ABORT OFF; BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , ,--此处有语法错误 N'测试自动回滚' ); UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚1'; COMMIT TRAN;
执行消息:
消息 102,级别 15,状态 1,第 14 行
“,”附近有语法错误。
可以看出:设置自动回滚为OFF后,Insert语句有语法错误,并没有继续执行Update语句,事务仍然自动回滚;
SET XACT_ABORT { ON | OFF }的情况下,系统会在执行事务之前,默认设置为OFF。
3.捕捉事务执行过程中的错误:
BEGIN TRAN; BEGIN TRY INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , 9999999999999999999 ,--此处有语法错误 N'测试自动回滚' ); END TRY BEGIN CATCH ROLLBACK TRAN;--如果检查到try语句块中有异常,则回滚事务 RETURN;--退出执行,return后面的语句不执行 END CATCH; UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚'; COMMIT TRAN;
执行消息:
(0 行受影响)
可以看出:事务只执行了Insert语句,而Insert失败,有0行受影响;因为使用了try-catch,所以消息中没有错误消息;(try-catch用法参见https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008-r2/ms175976(v=sql.105))
注意:ROLLBACK TRAN 后要加return退出执行,否则后面的Update会另起事务继续执行;
(2).使用@@ERROR来检测错误:
BEGIN TRAN; INSERT INTO dbo.Material_PO_PipeMaterialOrder ( ID , OrderNO , OrderName , Status , RMDSC ) VALUES ( NEWID() , N'测试自动回滚' , N'测试自动回滚' , 9999999999999999999 ,--此处有语法错误 N'测试自动回滚' ); IF ( @@ERROR <> 0 )--如果检查到错误 BEGIN ROLLBACK TRAN;--回滚事务 RETURN;--退出执行,return后面的语句不执行 END; UPDATE dbo.Material_PO_PipeMaterialOrder SET OrderNO = '测试自动回滚'; COMMIT TRAN;
执行消息:
消息 8115,级别 16,状态 2,第 3 行
将 expression 转换为数据类型 int 时出现算术溢出错误。
语句已终止。
可以看出:检查到错误后,事务回滚,且显示错误消息