Vous n'êtes pas identifié(e).

#1 23/12/2016 12:31:45

Mlan2
Membre

Gestion des COMMIT sous PostgreSQL

Bonjour,

Je m'interroge sur un problème que je rencontre dans l'écriture d'une fonction.

Dans la documentation de PostgreSQL,Il est dit que PostgreSQL fonctionne en autoCommit.
Je comprends par là qu'à chaque action sur un enregistrement (INSERT, DELETE, UPDATE), cette action est enregistrée dans la table.

Or dans mon exemple de fonction ci-dessous, je constate que, si une instruction provoque une erreur, les actions réalisées précédemment (3 INSERT) ne sont pas enregistrées dans la table, comme si un ROLLBACK aurait été fait (annulant les actions précédentes).

Dans l'exemple de la fonction, 3 actions INSERT sont réalisées, puis suit une action provoquant une erreur.

Dans un bloc EXCEPTION interceptant l'erreur, 2 actions INSERT différentes sont réalisées.

Quand je regarde le résultat obtenu dans la table, je constate uniquement les 2 actions INSERT effectuées dans le bloc Exception.
Les actions INSERT précédentes n'apparaissent pas, comme si le COMMIT ne se faisait pas ou aurait été annulé par un ROLLBACK.

Quelqu'un peut t'il éclairer ma lanterne sur ce qui se passe réellement ?

Peut t'on obtenir le résultat que je souhaite, et quel serait la méthode ?

D'avance merci de votre retour.


CREATE OR REPLACE  FUNCTION MyFunction (PAR_1  varchar,
                                        PAR_2  varchar) RETURNS INTEGER
AS

$$
DECLARE

  C_Ret            INTEGER;                -- Code retour de fonction.

BEGIN

  C_Ret        := 0;

  INSERT INTO TAB1   (FIELD1, FIELD2)
              VALUES ('VAL11', 'VAL21');

  INSERT INTO TAB1   (FIELD1, FIELD2)
              VALUES ('VAL12', 'VAL22');

  INSERT INTO TAB1   (FIELD1, FIELD2)
              VALUES ('VAL13', 'VAL23');
              
  Instruction SQL provoquant une erreur.

  RETURN C_Ret;
  
  EXCEPTION

    WHEN OTHERS THEN
    BEGIN
    
      INSERT INTO TAB1   (FIELD1, FIELD2)
              VALUES ('VAL14', 'VAL24');

      INSERT INTO TAB1   (FIELD1, FIELD2)
              VALUES ('VAL15', 'VAL25');
    
    
      C_Ret := 2;
      RETURN C_Ret;
    END;

END;
$$ LANGUAGE plpgsql;

Hors ligne

#2 23/12/2016 14:13:05

rjuju
Administrateur

Re : Gestion des COMMIT sous PostgreSQL

Une procédure stockée est considérée comme une opération atomique, le comportement est donc normal.  Vous voulez probablement la fonctionnalité de SAVEPOINT / ROLLBACK TO : http://docs.postgresql.fr/9.6/sql-savepoint.html

Hors ligne

#3 23/12/2016 15:22:54

Mlan2
Membre

Re : Gestion des COMMIT sous PostgreSQL

Merci de la réponse.

L'instruction SAVEPOINT me parait effectivement adaptée pour mon exemple.

Je l'ai mis en oeuvre, mais je constate que cette instruction n'est pas autorisée dans le langage PL/pgsql.

Si une procédure stockée est considérée comme une opération atomique, peux t'on imaginer que dans mon exemple, les INSERT seraient réalisés par l'appel à une procédure stockée, on obtiendrait le résultat attendu ?

Je vais faire l'essai dans ce sens.

D'avance merci de votre retour.

Hors ligne

#4 23/12/2016 17:55:02

rjuju
Administrateur

Re : Gestion des COMMIT sous PostgreSQL

Effectivement SAVEPOINT ne marche pas en pl/pgsql.  Pour votre besoin, il faut utiliser de multiples blocs BEGIN ... EXCEPTION à la place.

Hors ligne

#5 23/12/2016 20:07:48

Mlan2
Membre

Re : Gestion des COMMIT sous PostgreSQL

Merci de l'information.

Comment alors le réaliser ?

Auriez-vous un exemple à me proposer ?

Ce que je cherche à obtenir est avoir l'assurance que les 3 INSERTS soient réellement effectués avant la ligne en erreur.

Pourrait t'on forcer l'exécution d'un bloc de code EXCEPTION dans lequel seraient enregistrées les 3 lignes d'INSERT ? (RAISE ?)

Merci pour vos propositions.

Hors ligne

#6 24/12/2016 14:37:21

rjuju
Administrateur

Re : Gestion des COMMIT sous PostgreSQL

Mettez un ou plusieurs blocs BEGIN ... EXCEPTION autour de la ou les instructions problématiques.

Hors ligne

Pied de page des forums