萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL Server TRY...CATCH 捕獲錯誤詳解:ERROR_MESSAGE/SEVERITY/STATE 完整取得與重拋

標準錯誤處理模板

BEGIN TRY
    -- 業務邏輯:可能拋出錯誤的 DML/DDL
    INSERT INTO accounts (id, balance) VALUES (1, -100);  -- 假設有 CHECK 約束 balance >= 0
END TRY
BEGIN CATCH
    -- 1. 取得錯誤詳情
    DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
    DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
    DECLARE @ErrorState INT = ERROR_STATE();

    -- 2. 記錄日誌(自定義表)
    INSERT INTO error_log (err_msg, severity, state, proc_name, log_time)
    VALUES (@ErrorMessage, @ErrorSeverity, @ErrorState, 'usp_Transfer', SYSDATETIME());

    -- 3. 重新拋出(保持原始錯誤資訊給上層)
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;

核心錯誤函式(僅在 CATCH 區塊有效)

函式回傳說明
ERROR_NUMBER()int錯誤號(如 547 為 FK 衝突)
ERROR_SEVERITY()int嚴重級 1–25(≥20 為系統致命)
ERROR_STATE()int錯誤狀態碼,同錯誤號不同位置可能不同
ERROR_PROCEDURE()sysname發生錯誤的預存程序/觸發器名
ERROR_LINE()int批次/程序內行號
ERROR_MESSAGE()nvarchar(4000)完整錯誤文本(含參數值)

RAISERROR 重拋參數

RAISERROR (msg_str, severity, state [, argument ...] )
-- 或格式化
RAISERROR (N'自訂訊息: %s, 代碼: %d', 16, 1, @param1, @param2);
  • severity 0–18 使用者可拋,19–25 需 sysadmin 權限且需 WITH LOG。
  • state 0–255,建議保持原 ERROR_STATE(),便於追蹤來源。

THROW(SQL 2012+ 推薦)

BEGIN CATCH
    THROW;  -- 直接重拋原始錯誤,保留堆疊、行號、狀態,語法更簡潔
END CATCH;
  • THROW 不需變數,自動保留完整錯誤上下文。
  • 若需自訂訊息:THROW 50001, '自訂業務錯誤', 1;

交易控制整合

BEGIN TRY
    BEGIN TRANSACTION;
    -- 多條 DML
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    THROW;
END CATCH;

總結

TRY...CATCH + ERROR_*() 函式是 SQL Server 結構化錯誤處理基石。生產環境建議:統一錯誤日誌表、CATCH 區塊記錄完整上下文、用 THROW 重拋,確保監控系統能精準告警、開發能快速定位。

copyright © 萬盛學電腦網 all rights reserved