Nidificazione delle transazioni

Le transazioni esplicite possono essere nidificate. Ciò consente principalmente il supporto delle transazioni all'interno di stored procedure che è possibile richiamare sia da un processo già incluso in una transazione che da processi privi di transazioni attive.

Nell'esempio seguente viene illustrato l'utilizzo delle transazioni nidificate. La procedura TransProc applica la rispettiva transazione indipendentemente dalla modalità impostata in ogni processo da cui viene eseguita. Se la procedura TransProc viene richiamata quando una transazione è attiva, la transazione nidificata in TransProc viene ignorata e, a seconda dell'azione finale eseguita per la transazione esterna, viene eseguito il commit o il rollback delle relative istruzioni INSERT. Se la procedura TransProc viene eseguita da un processo privo di transazione attiva, l'istruzione COMMIT TRANSACTION alla fine della procedura esegue correttamente il commit delle istruzioni INSERT.

SET QUOTED_IDENTIFIER OFF;
GO
SET NOCOUNT OFF;
GO
USE AdventureWorks;
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

Il commit delle transazioni interne viene ignorato da the Motore di database di SQL Server. A seconda dell'operazione eseguita alla fine della transazione più esterna, viene eseguito il commit o il rollback della transazione. In caso di commit della transazione esterna, viene eseguito il commit anche delle transazioni nidificate e in caso di rollback della transazione esterna viene eseguito il rollback anche di tutte le transazioni interne, indipendentemente dal fatto che sia stato eseguito il commit delle singole transazioni interne.

Ogni chiamata di COMMIT TRANSACTION o COMMIT WORK viene applicata all'ultima istruzione BEGIN TRANSACTION eseguita. Se le istruzioni BEGIN TRANSACTION sono nidificate, l'istruzione COMMIT viene applicata solo alla transazione più interna, anche se un'istruzione COMMIT TRANSACTION transaction_name all'interno di una transazione nidificata fa riferimento al nome della transazione esterna.

Il parametro transaction_name di un'istruzione ROLLBACK TRANSACTION non può fare riferimento alle transazioni interne di una serie di transazioni nidificate denominate. transaction_name può fare riferimento solo al nome della transazione più esterna. Se a qualsiasi livello di un set di transazioni nidificate viene eseguita un'istruzione ROLLBACK TRANSACTION transaction_name che fa riferimento alla transazione esterna, viene eseguito il rollback dell'intera serie di transazioni interne. Se a qualsiasi livello di un set di transazioni nidificate viene eseguita un'istruzione ROLLBACK WORK o ROLLBACK TRANSACTION priva del parametro transaction_name, viene eseguito il rollback di tutte le transazioni nidificate, compresa la transazione esterna.

La funzione @@TRANCOUNT registra il livello di nidificazione corrente delle transazioni. Ogni istruzione BEGIN TRANSACTION incrementa @@TRANCOUNT di un'unità, mentre ogni istruzione COMMIT TRANSACTION o COMMIT WORK decrementa @@TRANCOUNT di un'unità. Un'istruzione ROLLBACK WORK o ROLLBACK TRANSACTION in cui non è indicato il nome della transazione esegue il rollback di tutte le transazioni nidificate e decrementa @@TRANCOUNT fino al valore 0. Un'istruzione ROLLBACK TRANSACTION in cui viene indicato il nome della transazione più esterna di una serie di transazioni nidificate esegue il rollback di tutte le transazioni nidificate e decrementa @@TRANCOUNT fino al valore 0. Per determinare se ci si trova all'interno di una transazione, verificare se il valore di SELECT @@TRANCOUNT è 1 o un valore maggiore. Se @@TRANCOUNT è 0, non ci si trova all'interno di una transazione.