首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server TRY...CATCH 錯誤捕獲:獲取錯誤消息、嚴重級別、狀態碼完整模板

     編輯:MySQL 資料庫相關知識

T-SQLTRY...CATCH結構化異常處理中,系統函數ERROR_MESSAGE()、ERROR_SEVERITY()、ERROR_STATE()配合RAISERROR重拋,構建標準錯誤處理閉環。本文提供生產級模板與關鍵函數解析。

標準模板


BEGIN TRY
    -- 業務邏輯:可能拋錯的 SQL
    INSERT INTO orders (user_id, amount) VALUES (100, -50); -- 假設 amount 有 CHECK 約束
    UPDATE accounts SET balance = balance - 50 WHERE user_id = 100;
END TRY
BEGIN CATCH
    -- 1. 獲取錯誤資訊
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT 
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    -- 2. 記錄日誌(可選:寫入錯誤日誌表)
    -- INSERT INTO error_log (msg, severity, state, proc, time) 
    -- VALUES (@ErrorMessage, @ErrorSeverity, @ErrorState, ERROR_PROCEDURE(), GETDATE());

    -- 3. 重拋錯誤給調用端(保持原始嚴重級別與狀態)
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;

核心系統函數詳解

函數返回值說明
ERROR_NUMBER()INT錯誤號(如 547 外鍵衝突, 2627 唯一鍵衝突)
ERROR_SEVERITY()INT嚴重級別 1-25(>10 為系統錯誤,16-18 可由用戶修復,19-25 需管理員)
ERROR_STATE()INT狀態碼,同一錯誤不同觸發點有不同州,助定位
ERROR_PROCEDURE()SYSNAME發生錯誤的存儲過程/觸發器名(動態SQL中為NULL)
ERROR_LINE()INT批次/過程內行號
ERROR_MESSAGE()NVARCHAR(4000)完整錯誤文本(含參數值,如欄位名、表名)

進階模式:嵌套 TRY...CATCH 與事務控制


BEGIN TRY
    BEGIN TRANSACTION;
    
    BEGIN TRY
        -- 子操作1
        INSERT ...
    END TRY
    BEGIN CATCH
        -- 子操作1失敗邏輯
        ROLLBACK TRANSACTION;
        THROW; -- SQL Server 2012+ 推薦用 THROW 重拋,保留原始堆疊
    END CATCH

    BEGIN TRY
        -- 子操作2
        UPDATE ...
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        THROW;
    END CATCH

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    -- 統一錯誤處理
    DECLARE @msg NVARCHAR(4000) = ERROR_MESSAGE();
    RAISERROR(@msg, 16, 1); -- 或 THROW
END CATCH

THROW vs RAISERROR(2012+ 推薦 THROW)

  • THROW:無需聲明變量,自動保留原始錯誤號、嚴重級別、狀態、堆疊;語法簡潔THROW;或THROW 50000, '自定義消息', 1;
  • RAISERROR:需手動捕獲變量,支援格式化佔位符%s %d,向後兼容

最佳實踐清單

  1. 所有存儲過程/觸發器頂層包裹TRY...CATCH
  2. CATCH塊首檢查@@TRANCOUNT > 0回滾
  3. 錯誤寫入集中日誌表(含時間、會話、用戶、SQL片段)
  4. 業務錯誤用THROW 50000+自定義錯誤號,區分系統錯誤
  5. 避免在CATCH中吞噬錯誤不重拋(除非刻意靜默)

標準化錯誤捕獲模板,讓異常從「黑盒崩潰」變為「可觀測、可追蹤、可恢復」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved