Vous n'êtes pas identifié(e).
Pages : 1
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
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
Julien.
https://rjuju.github.io/
Hors ligne
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
Effectivement SAVEPOINT ne marche pas en pl/pgsql. Pour votre besoin, il faut utiliser de multiples blocs BEGIN ... EXCEPTION à la place.
Julien.
https://rjuju.github.io/
Hors ligne
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
Mettez un ou plusieurs blocs BEGIN ... EXCEPTION autour de la ou les instructions problématiques.
Julien.
https://rjuju.github.io/
Hors ligne
Pages : 1