交易儲存點
儲存點 (Savepoint) 提供回復部分交易的機制。您可以使用 SAVE TRANSACTION savepoint_name 陳述式來建立儲存點。接著再執行 ROLLBACK TRANSACTION savepoint_name 陳述式回復到儲存點,而非回復到交易的起點。
不太可能發生錯誤時,儲存點特別有用。發生不常見的錯誤時,使用儲存點來回復部分交易,比在進行更新之前,測試每筆交易來查看是否可以更新要更為有效。更新與回復都是費時的動作,因此儲存點只有在遇到錯誤的可能性不高,且事前檢查更新可用性的成本相當高的情形下才有效率。
此範例顯示訂單系統中的儲存點使用範例,此系統由於公司的供應商與訂貨點充足,因此發生缺貨的可能性不高。應用程式通常會在嘗試進行記錄訂單的更新之前,先證實手邊的存貨已經足夠。基於某種原因,這個範例假設要事先驗證可用的存貨量是相當費時的 (由於使用低速數據機或 WAN 連接)。應用程式可以撰寫成僅進行更新,並於發生存貨不足的錯誤時回復更新。在這種情況下,插入資料之後快速檢查 @@ERROR 比更新之前驗證數量要快得多。
InvCtrl 資料表擁有 CHECK 條件約束,可在 QtyInStk 資料行降至 0 以下時觸發 547 的錯誤。OrderStock 程序可建立儲存點。如果發生 547 錯誤,便回復到儲存點,並將手邊的項目數量傳回呼叫的處理序 (Process)。然後呼叫的處理序便可取代手邊的訂單數量。如果 OrderStock 傳回 0,呼叫的處理序便知道手邊的存貨足以履行訂單。
SET NOCOUNT OFF;
GO
USE AdventureWorks;
GO
CREATE TABLE InvCtrl
(WhrhousID int,
PartNmbr int,
QtyInStk int,
ReordrPt int,
CONSTRAINT InvPK PRIMARY KEY
(WhrhousID, PartNmbr),
CONSTRAINT QtyStkCheck CHECK (QtyInStk > 0) );
GO
CREATE PROCEDURE OrderStock
@WhrhousID int,
@PartNmbr int,
@OrderQty int
AS
DECLARE @ErrorVar int;
SAVE TRANSACTION StkOrdTrn;
UPDATE InvCtrl SET QtyInStk = QtyInStk - @OrderQty
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr;
SELECT @ErrorVar = @@error;
IF (@ErrorVar = 547)
BEGIN
ROLLBACK TRANSACTION StkOrdTrn;
RETURN (SELECT QtyInStk
FROM InvCtrl
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr);
END
ELSE
RETURN 0;
GO