SQL Server 2005 引入了 TRY...CATCH 結構,讓開發人員能夠在 T-SQL 存儲過程中實現結構化的錯誤處理,這是相較於 SQL Server 2000 僅能依賴 @@ERROR 全域變數的一大進步。不過需注意:TRY...CATCH 僅能捕獲嚴重度 11 到 19 的運行時錯誤,無法捕獲連接中斷、語法錯誤或編譯錯誤等嚴重度 20 以上的系統級異常。
BEGIN TRY
-- 可能引發錯誤的 T-SQL 陳述式
END TRY
BEGIN CATCH
-- 錯誤處理邏輯
-- 可使用 ERROR_NUMBER(), ERROR_MESSAGE(), ERROR_SEVERITY() 等函數獲取錯誤詳情
END CATCH
以下存儲過程示範如何在插入操作中套用 TRY...CATCH,確保資料完整性並回傳自增主鍵或錯誤代碼:
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
ALTER PROCEDURE [dbo].[P_DangerSource_File_Add]
@SourceName VARCHAR(50), -- 名稱
@TypeID INT, -- 類型
@DangerLevel VARCHAR(30), -- 危險級別
@IsControl BIT, -- 是否監控
@SourceLocation VARCHAR(200), -- 危險源地點
@SourceNum INT, -- 危險源數量
@Descrip VARCHAR(200), -- 描述
@Accident VARCHAR(150), -- 可能發生事故
@Summarize VARCHAR(200), -- 概述
@Supervisor VARCHAR(30), -- 負責人
@Telephone VARCHAR(50), -- 聯絡電話
@UserID VARCHAR(50), -- 登記人 ID
@InDate DATETIME, -- 登記日期
@IsChanged BIT, -- 是否變更
@DeptID VARCHAR(20) -- 部門 ID
AS
BEGIN
BEGIN TRY
INSERT INTO T_DangerSource_File (
[SourceName], [TypeID], [DangerLevel], [IsControl],
[SourceLocation], [SourceNum], [Descrip], [Accident],
[Summarize], [Supervisor], [Telephone], [UserID],
[InDate], [IsChanged], [DeptID]
) VALUES (
@SourceName, @TypeID, @DangerLevel, @IsControl,
@SourceLocation, @SourceNum, @Descrip, @Accident,
@Summarize, @Supervisor, @Telephone, @UserID,
@InDate, @IsChanged, @DeptID
);
-- 成功時回傳新增記錄的自增 ID
RETURN SCOPE_IDENTITY();
END TRY
BEGIN CATCH
-- 發生錯誤時回傳 -1,實際專案建議記錄錯誤日誌
RETURN -1;
END CATCH
END
建議:在 CATCH 區塊中記錄錯誤至自訂日誌表,並視業務需求決定是否重新拋出錯誤(THROW 或 RAISERROR),讓上層應用程式得知失敗原因。
TRY...CATCH 不支援跨越 BEGIN/COMMIT TRANSACTION 邊界CATCH善用 TRY...CATCH 能讓存儲過程更健壯,搭配 SCOPE_IDENTITY() 回傳新增 ID,是 SQL Server 2005+ 開發的標準作法。