保存點提供了一種機(jī)制,用于回滾部分事務(wù)??梢允褂?SAVE TRANSACTION savepoint_name 語句創(chuàng)建一個保存點,然后再執(zhí)行 ROLLBACK TRANSACTION savepoint_name 語句回滾到該保存點,從而無須回滾到事務(wù)的開始。
在不可能發(fā)生錯誤的情況下,保存點很有用。在很少出現(xiàn)錯誤的情況下使用保存點回滾部分事務(wù),比讓每個事務(wù)在更新之前測試更新的有效性更為有效。更新和回滾操作代價很大,因此只有在遇到錯誤的可能性很小,而且預(yù)先檢查更新的有效性的代價相對很高的情況下,使用保存點才會非常有效。
下面的示例顯示保存點在一個訂購系統(tǒng)中的使用情況。該系統(tǒng)中存貨不足的可能性很小,因為該公司具備有效的供應(yīng)商和再訂購點。通常應(yīng)用程序在嘗試更新訂購記錄時,會先驗證手邊是否有足夠的存貨。該示例假定由于某種原因(如連接到一個低速的調(diào)制解調(diào)器或廣域網(wǎng)上),先驗證可用存貨的數(shù)量代價相對較大。可將應(yīng)用程序編寫為只進(jìn)行更新,而且如果收到錯誤信息,表明庫存不足時,將回滾該更新。在這種情況下,在插入之后快速檢查 @@ERROR 比在更新之前驗證庫存數(shù)量速度要快得多。
InvCtrl 表有一個 CHECK 約束,如果 QtyInStk 列低于 0,就會觸發(fā) 547 號錯誤。OrderStock 過程創(chuàng)建一個保存點。如果出現(xiàn) 547 錯誤,它將回滾到該保存點,并將當(dāng)前手邊有的項目數(shù)返回給調(diào)用進(jìn)程。然后調(diào)用進(jìn)程可以決定是否需要針對手邊現(xiàn)有的數(shù)量重新下訂單。如果 OrderStock 返回一個 0,則調(diào)用進(jìn)程知道當(dāng)前有足夠的存貨,可以滿足訂購需要。
SET NOCOUNT OFF
GO
USE pubs
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
BEGIN TRANSACTION StkStock
DECLARE @ErrorVar int
SAVE TRANSACTION StkOrdTrn
UPDATE InvCtrl SET QtyInStk = QtyInStk - @OrderQty
WHERE WhrhousID = 1
AND PartNmbr = 1
SELECT @ErrorVar = @@error
IF (@ErrorVar = 547)
BEGIN
ROLLBACK TRANSACTION StkOrdTrn
RETURN (SELECT QtyInStk
FROM InvCtrl
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr)
COMMIT TRANSACTION
END
ELSE
COMMIT TRANSACTION
RETURN 0
GO
insert InvCtrl(WhrhousID,PartNmbr,QtyInStk)values(1,1,2)
update InvCtrl set QtyInStk=2 where WhrhousID=1
exec OrderStock 1,1,1
在不可能發(fā)生錯誤的情況下,保存點很有用。在很少出現(xiàn)錯誤的情況下使用保存點回滾部分事務(wù),比讓每個事務(wù)在更新之前測試更新的有效性更為有效。更新和回滾操作代價很大,因此只有在遇到錯誤的可能性很小,而且預(yù)先檢查更新的有效性的代價相對很高的情況下,使用保存點才會非常有效。
下面的示例顯示保存點在一個訂購系統(tǒng)中的使用情況。該系統(tǒng)中存貨不足的可能性很小,因為該公司具備有效的供應(yīng)商和再訂購點。通常應(yīng)用程序在嘗試更新訂購記錄時,會先驗證手邊是否有足夠的存貨。該示例假定由于某種原因(如連接到一個低速的調(diào)制解調(diào)器或廣域網(wǎng)上),先驗證可用存貨的數(shù)量代價相對較大。可將應(yīng)用程序編寫為只進(jìn)行更新,而且如果收到錯誤信息,表明庫存不足時,將回滾該更新。在這種情況下,在插入之后快速檢查 @@ERROR 比在更新之前驗證庫存數(shù)量速度要快得多。
InvCtrl 表有一個 CHECK 約束,如果 QtyInStk 列低于 0,就會觸發(fā) 547 號錯誤。OrderStock 過程創(chuàng)建一個保存點。如果出現(xiàn) 547 錯誤,它將回滾到該保存點,并將當(dāng)前手邊有的項目數(shù)返回給調(diào)用進(jìn)程。然后調(diào)用進(jìn)程可以決定是否需要針對手邊現(xiàn)有的數(shù)量重新下訂單。如果 OrderStock 返回一個 0,則調(diào)用進(jìn)程知道當(dāng)前有足夠的存貨,可以滿足訂購需要。
SET NOCOUNT OFF
GO
USE pubs
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
BEGIN TRANSACTION StkStock
DECLARE @ErrorVar int
SAVE TRANSACTION StkOrdTrn
UPDATE InvCtrl SET QtyInStk = QtyInStk - @OrderQty
WHERE WhrhousID = 1
AND PartNmbr = 1
SELECT @ErrorVar = @@error
IF (@ErrorVar = 547)
BEGIN
ROLLBACK TRANSACTION StkOrdTrn
RETURN (SELECT QtyInStk
FROM InvCtrl
WHERE WhrhousID = @WhrhousID
AND PartNmbr = @PartNmbr)
COMMIT TRANSACTION
END
ELSE
COMMIT TRANSACTION
RETURN 0
GO
insert InvCtrl(WhrhousID,PartNmbr,QtyInStk)values(1,1,2)
update InvCtrl set QtyInStk=2 where WhrhousID=1
exec OrderStock 1,1,1