預存程序中正確處理事務是保證資料一致性的關鍵。本文展示三種常見事務處理模式的完整程式碼範例,涵蓋 XACT_ABORT、@@ERROR 檢查、TRY...CATCH 結構化異常處理,助您選擇最適合的方案。
IF EXISTS (SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[USP_ProcedureWithTransaction_Demo]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
GO
CREATE PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
AS
BEGIN
SET XACT_ABORT ON -- 發生執行錯誤自動回滾整個事務
BEGIN TRANSACTION
INSERT INTO Lock(LockTypeID) VALUES('A') -- 故意錯誤:LockTypeID 為 int
UPDATE Lock SET LockTypeID = 2 WHERE LockID = 32
COMMIT TRANSACTION
SET XACT_ABORT OFF
END
GO
特點:簡潔,運行時錯誤(如類型轉換失敗、主鍵衝突)自動觸發全事務回滾,無需手動判斷。
IF EXISTS (SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[USP_ProcedureWithTransaction_Demo]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
GO
CREATE PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
AS
BEGIN
BEGIN TRANSACTION
INSERT INTO Lock(LockTypeID) VALUES('A') -- 故意錯誤
UPDATE Lock SET LockTypeID = 1 WHERE LockID = 32
COMMIT TRANSACTION
IF (@@ERROR <> 0) -- 僅檢查最後一條語句錯誤
ROLLBACK TRANSACTION
END
GO
缺點:@@ERROR 僅反映最後一條語句狀態,若中間語句失敗但後續成功,無法捕捉;需在每條關鍵語句後檢查並配合 GOTO 跳轉,代碼冗長易出錯。
IF EXISTS (SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[USP_ProcedureWithTransaction_Demo]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
DROP PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
GO
CREATE PROCEDURE [dbo].[USP_ProcedureWithTransaction_Demo]
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
UPDATE Lock SET LockTypeID = 1 WHERE LockID = 32
INSERT INTO Lock(LockTypeID) VALUES('A') -- 故意錯誤
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
-- 可在此記錄錯誤資訊:ERROR_NUMBER(), ERROR_MESSAGE(), ERROR_LINE() 等
END CATCH
END
GO
-- 測試執行
EXEC [USP_ProcedureWithTransaction_Demo]
優勢: