事務在執行過程中報錯的處理方式
1.系統在預設情況下:
a.在事務執行過程中遇到執行時的報錯,不會回滾整個事務,會繼續執行報錯後面的語句;舉例如下:
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語句(有行數受影響),沒有回滾事務
b.在事務執行過程中遇到編譯時的報錯(如語法錯誤等),會回滾整個事務,報錯後面的語句不會執行;舉例如下:
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 Server 語句出現執行時錯誤時, Transact-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)注意點:
a.如果錯誤很嚴重,那麼即使 SET XACT_ABORT 為 OFF,也可能回滾整個事務;
b.編譯錯誤(如語法錯誤)都會回滾事務,不受 SET XACT_ABORT 的影響,舉例如下:
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語句,事務仍然自動回滾;
c. 在不手動設定 SET XACT_ABORT { ON | OFF }的情況下,系統會在執行事務之前,預設設定為OFF。
3.捕捉事務執行過程中的錯誤:
(1)使用try-catch捕獲異常:
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 時出現算術溢位錯誤。
語句已終止。
可以看出:檢查到錯誤後,事務回滾,且顯示錯誤訊息