Using Transaction Procedure Template
問題描述
在 SQL Server 中撰寫具有交易(Transaction)控制的預存程序,若考慮預存程序會被另一個預存程序或觸發呼叫,如上圖 ProcedureA 呼叫 ProcedureB,在兩個預存程序中均可能發生錯誤需要進行 Rollback Transaction,此時交易控制不能如下段這般簡單BEGIN TRY BEGIN TRANSACTION; -- Do Something COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; END CATCH;
解決方案
此時需要做一點手腳,以下這個範本適用在主要預存程序或被呼叫附屬預存程序,撰寫時不需要額外傳遞交易狀態等參數。DECLARE @hasOuterTransaction bit = case when @@trancount > 0 then 1 else 0 end;
DECLARE @rollbackPoint nvarchar(32)=replace(convert(nchar(36), newid()), N'-', N'');
BEGIN TRY
IF @hasOuterTransaction = 1
BEGIN
SAVE TRANSACTION @rollbackPoint;
END
ELSE
BEGIN
BEGIN TRANSACTION @rollbackPoint;
END;
-- Do Something
IF @hasOuterTransaction = 0
BEGIN
COMMIT TRANSACTION @rollbackPoint;
END;
END TRY
BEGIN CATCH
IF xact_state() = 1
BEGIN
ROLLBACK TRANSACTION @rollbackPoint;
END;
DECLARE @error_message nvarchar(1000)=ERROR_MESSAGE();
THROW 51000, @error_message, 1;
END CATCH;
重點在
- 需要判斷當交易已經開啟時,使用 SAVE 指令。
- 執行 BEGIN , COMMIT, ROLLBACK 指令時均指定 Transaction 名稱,COMMIT 與 ROLLBACK 是否要執行得視交易當下的狀態。