1. 程式人生 > >事務在執行過程中報錯的處理方式

事務在執行過程中報錯的處理方式

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 時出現算術溢位錯誤。

語句已終止。

可以看出:檢查到錯誤後,事務回滾,且顯示錯誤訊息