Transact-SQL 執行過程中難免發生錯誤。SQL Server 2005 提供兩層錯誤捕捉機制:用戶端程式碼 (C#、Java 等) 的 try...catch,以及 T-SQL 內建的錯誤處理。後者對邏輯錯誤、自訂錯誤處理更靈活。本文系統整理 T-SQL 錯誤處理技術。
T-SQL 僅能捕捉非致命錯誤 (如鍵值衝突),無法捕捉致命錯誤 (語法錯誤)。系統變數 @@ERROR 記錄最近一條陳述式的錯誤號:成功為 0,失敗為錯誤號。必須緊接在可能出錯的陳述式之後檢查,因後續任何成功陳述式都會將其重置為 0。
INSERT INTO table1 VALUES(1, 'aa');
INSERT INTO table1 VALUES(1, 'bb'); -- 主鍵衝突
IF @@ERROR > 0
PRINT '鍵值衝突';
將錯誤編號 (50001 起)、嚴重等級、訊息文字登錄至系統表,再由 RAISERROR 拋出。支援多語言:英文版用 %s、%d,本地化版用 %1!、%2! 格式。
EXEC sp_addmessage @msgnum=50001, @severity=16,
@msgtext='sql encounter an error(%s).', @lang='us_english';
EXEC sp_addmessage @msgnum=50001, @severity=16,
@msgtext='sql遇到了一個錯誤(%1!).', @lang='Traditional Chinese';
RAISERROR(50001, 16, 1, '測試');
不想耦合系統表,可直接拋出:
RAISERROR('sql遇到了一個錯誤(%s)', 16, 1, '測試');
優點:可攜性高;缺點:錯誤訊息分散在程式碼中。
提供結構化錯誤處理,類似程式語言:
BEGIN TRY
-- 可能出錯的 T-SQL 批次
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrNo,
ERROR_MESSAGE() AS ErrMsg,
ERROR_SEVERITY() AS Severity,
ERROR_STATE() AS State,
ERROR_LINE() AS LineNo;
-- 記錄錯誤、回滾交易等
END CATCH
TRY...CATCH 可捕捉批次內大多數非致命錯誤,配合 ERROR_*() 函數取得詳細錯誤資訊,是現代 T-SQL 錯誤處理的首選模式。