巢狀交易

外顯交易可以是巢狀的。其主要目的是要支援預存程序中的交易,讓交易可以被已經在交易中的處理序呼叫,或沒有動作的交易內的處理序呼叫。

下列範例顯示巢狀交易的使用意圖。TransProc 程序會強制執行其交易,而不論執行此程序之處理序的交易模式為何。如果是在交易使用中時呼叫 TransProc,在 TransProc 中的巢狀交易大部份會被忽略,並且依照外部交易最後執行的動作,來認可或回復其中的 INSERT 陳述式。如果執行 TransProc 的處理序沒有尚未處理的交易,在程序結尾的 COMMIT TRANSACTION 便會有效地認可 INSERT 陳述式。

SET QUOTED_IDENTIFIER OFF;
GO
SET NOCOUNT OFF;
GO
USE AdventureWorks2008R2;
GO
CREATE TABLE TestTrans(Cola INT PRIMARY KEY,
               Colb CHAR(3) NOT NULL);
GO
CREATE PROCEDURE TransProc @PriKey INT, @CharCol CHAR(3) AS
BEGIN TRANSACTION InProc
INSERT INTO TestTrans VALUES (@PriKey, @CharCol)
INSERT INTO TestTrans VALUES (@PriKey + 1, @CharCol)
COMMIT TRANSACTION InProc;
GO
/* Start a transaction and execute TransProc. */
BEGIN TRANSACTION OutOfProc;
GO
EXEC TransProc 1, 'aaa';
GO
/* Roll back the outer transaction, this will
   roll back TransProc's nested transaction. */
ROLLBACK TRANSACTION OutOfProc;
GO
EXECUTE TransProc 3,'bbb';
GO
/* The following SELECT statement shows only rows 3 and 4 are 
   still in the table. This indicates that the commit
   of the inner transaction from the first EXECUTE statement of
   TransProc was overridden by the subsequent rollback. */
SELECT * FROM TestTrans;
GO

「SQL Server Database Engine」會忽略認可內部交易。交易的認可或復原是依照最外層的交易在最後所執行的動作而定。若是認可外部交易,則內部的巢狀交易也會被認可。若是復原外部交易,便會復原所有的內部交易,而不論內部交易是否個別被認可。

每個對於 COMMIT TRANSACTION 或 COMMIT WORK 的呼叫,皆套用於最後執行的 BEGIN TRANSACTION。如果 BEGIN TRANSACTION 陳述式是巢狀的,COMMIT 陳述式便僅套用於最後的巢狀交易,亦即最內層的交易。即使位於巢狀交易中的 COMMIT TRANSACTION transaction_name 陳述式參考的是外部交易的交易名稱,還是只會認可最內層的交易。

ROLLBACK TRANSACTION 陳述式的 transaction_name 參數參考一組具名巢狀交易的內部交易是不合法的。transaction_name 只能參考最外層交易的交易名稱。如果使用外部交易名稱的 ROLLBACK TRANSACTION transaction_name 陳述式,是在一組巢狀交易的任何層級執行,將會回復所有的巢狀交易。如果在一組巢狀交易的任何層級執行不包含 transaction_name 參數的 ROLLBACK WORK 或 ROLLBACK TRANSACTION 陳述式,它會回復所有巢狀交易,包括最外層的交易。

@@TRANCOUNT 函數記錄目前的交易巢狀層次。每個 BEGIN TRANSACTION 陳述式會使得 @@TRANCOUNT 加一。每個 COMMIT TRANSACTION 或 COMMIT WORK 陳述式會使得 @@TRANCOUNT 減一。ROLLBACK WORK 或 ROLLBACK TRANSACTION 陳述式,該陳述式並不會讓交易名稱回復所有巢狀交易並將 @@TRANCOUNT 遞減為 0。ROLLBACK TRANSACTION,它會在一組巢狀交易中使用最外部交易的交易名稱,這一組交易會回復所有巢狀交易,並將 @@TRANCOUNT 遞減為 0。當您不確定您是否已經在交易中時,SELECT @@TRANCOUNT 可判斷它是 1 還是 1 以上。如果 @@TRANCOUNT 是 0,則表示您不在交易中。