PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 13.18 » Programmation serveur » PL/pgSQL -- Langage de procédures SQL » Gestion des transactions

42.8. Gestion des transactions

Une nouvelle transaction démarre avec les caractéristiques de transaction avec leurs valeurs par défaut, comme le niveau d'isolation. Dans le cas où les transactions sont validées à l'intérieur d'une boucle, on peut désirer qu'une transaction démarre automatiquement avec les mêmes caractéristiques que la précédente. Les commandes COMMIT AND CHAIN et ROLLBACK AND CHAIN font cela.

Dans les procédures appelées par la commande CALL ainsi que dans les blocs de code anonymes (commande DO), il est possible de terminer les transactions en utilisant les commandes COMMIT et ROLLBACK. Une nouvelle transaction est démarrée automatiquement après qu'une transaction ait été terminée en utilisant ces commandes, donc il n'existe pas de commande START TRANSACTION. (Notez que BEGIN et END ont une signification différente dans PL/pgSQL.)

Voici un exemple simple :

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END
$$;

CALL transaction_test1();
   

Le contrôle des transactions est seulement possible dans les appels à CALL et DO à partir du plus haut niveau ou dans les appels imbriqués à CALL ou DO sans autre commande. Par exemple, si la pile d'appel est CALL proc1()CALL proc2()CALL proc3(), alors la deuxième et la troisième procédures peuvent exécuter les actions de contrôle de transaction. Mais si la pile d'appel est CALL proc1()SELECT func2()CALL proc3(), alors la dernière procédure ne peut pas faire de contrôle de transactions à cause du SELECT.

Des considérations spéciales s'appliquent aux boucles de curseur. Considérez cet exemple :

CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN SELECT * FROM test2 ORDER BY x LOOP
        INSERT INTO test1 (a) VALUES (r.x);
        COMMIT;
    END LOOP;
END;
$$;

CALL transaction_test2();
   

Habituellement, les curseurs sont automatiquement fermés au moment de la validation de la transaction. Néanmoins, un curseur créé dans une boucle comme celle-ci est automatiquement converti en un curseur maintenable par le premier COMMIT ou ROLLBACK. Ceci signifie que le curseur est complètement évalué au premier COMMIT ou ROLLBACK plutôt que ligne par ligne. Le curseur est toujours automatiquement supprimé après la boucle, donc c'est pratiquement invisible pour l'utilisateur.

Les commandes de transaction ne sont pas autorisées dans les boucles de curseur exécutés par des commandes qui ne sont pas en lecture seule (par exemple UPDATE ... RETURNING).

Une transaction ne peut pas être terminée dans un bloc contenant un gestionnaire d'exceptions.