Transactions imbriquées

Les transactions explicites peuvent être imbriquées. Cette fonctionnalité est avant tout destinée à la prise en charge des transactions dans les procédures stockées appelées par un processus faisant partie d'une transaction, ou par des processus ne disposant pas de transaction active.

L'exemple suivant illustre cette utilisation des transactions imbriquées. La procédure TransProc applique sa transaction quel que soit le mode de transaction du processus qui l'exécute. Si TransProc est appelée alors qu'une transaction est active, la transaction imbriquée dans TransProc est en grande partie ignorée, et les instructions INSERT qu'elle contient sont validées ou restaurées en fonction de la dernière action effectuée dans la transaction la plus externe. Si TransProc est exécutée par un processus pour lequel aucune transaction n'est en cours, l'instruction COMMIT TRANSACTION qui se trouve à la fin de la procédure déclenche la validation effective des instructions 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

La validation des transactions internes est ignorée par le Moteur de base de données SQL Server. La transaction est validée ou restaurée en fonction de l'action prise à la fin de la transaction la plus externe. Si la transaction externe est validée, les transactions imbriquées dans celle-ci le sont aussi. Si la transaction externe est restaurée, toutes les transactions internes le sont aussi, qu'elles aient été validées individuellement ou non.

Chaque appel à COMMIT TRANSACTION ou COMMIT WORK s'applique à la dernière instruction BEGIN TRANSACTION exécutée. Si les instructions BEGIN TRANSACTION sont imbriquées, une instruction COMMIT s'applique uniquement à la dernière transaction imbriquée, qui est la transaction la plus interne. Même si l'instruction COMMIT TRANSACTION transaction_name d'une transaction imbriquée fait référence à la transaction externe, seule la transaction interne est validée.

Le paramètre transaction_name d'une instruction ROLLBACK TRANSACTION ne doit pas faire référence aux transactions internes d'un groupe de transactions nommées imbriquées. transaction_name peut uniquement faire référence à la transaction la plus externe. Si une instruction ROLLBACK TRANSACTION transaction_name utilisant le nom de la transaction externe est exécutée à n'importe quel niveau d'un ensemble de transactions imbriquées, alors toutes les transactions imbriquées sont restaurées. Si une instruction ROLLBACK WORK ou ROLLBACK TRANSACTION est exécutée à un niveau d'imbrication quelconque sans que le paramètre transaction_name soit spécifié, toutes les transactions imbriquées, la plus externe comprise, sont restaurées.

La fonction @@TRANCOUNT enregistre le niveau d'imbrication de la transaction en cours. Chaque instruction BEGIN TRANSACTION incrémente la valeur de @@TRANCOUNT d'une unité. Chaque instruction COMMIT TRANSACTION ou COMMIT WORK la décrémente de la même valeur. Une instruction ROLLBACK WORK ou ROLLBACK TRANSACTION pour laquelle aucun nom de transaction n'est spécifié restaure toutes les transactions imbriquées et remet @@TRANCOUNT à 0. Une instruction ROLLBACK TRANSACTION dans laquelle le nom de la transaction la plus externe d'un groupe de transactions imbriquées est spécifié restaure toutes les transactions imbriquées et remet @@TRANCOUNT à 0. Si vous n'êtes pas sûr qu'une transaction est déjà active, utilisez l'instruction SELECT @@TRANCOUNT pour déterminer si sa valeur est égale ou supérieure 1 Si la valeur de @@TRANCOUNT est 0, vous n'êtes pas dans une transaction.