PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

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

#1 05/06/2011 16:44:12

bebert73
Membre

affinage de la section EXCEPTION d'une fonction PL/pgSQL

Bonjour,

ci-dessous un bout de code, qui fonctionne bien, il me renvoie un message d'erreur personnalisé quand la fonction déclenche l'exception TOO_MANY_ROWS (dans la fonction je fais des SELECT ... INTO STRICT ...)

ma question est de savoir si on peut affiner un peu plus la section EXCEPTION, pour que le message d'erreur indique plus précisément à quel endroit l'exception s'est déclenchée

Nota : on est bien d'accord que si je fais un SELECT ... INTO STRICT ..., c'est que normalement les tables sont conçues avec des contraintes de telles manière que le SELECT ne peut ramener qu'une seule ligne. L'EXCEPTION ne devrait donc jamais se déclencher, et à la limite on pourrait même s'en passer. Mon but en la mettant est juste de refaire une nouvelle vérification, au cas où il y a une erreur de conception des tables, ou encore au cas où ma requête est mal construite. Bref, c'est un peu la ceinture et les bretelles...

Alors, voilà le code :

CREATE TABLE test1 (
    classe        INTEGER        PRIMARY KEY,
    sous_classe    INTEGER,
    nom            VARCHAR(32)
);

CREATE TABLE test2 (
    classe        INTEGER    PRIMARY KEY,
    sous_classe    INTEGER,
    nom            VARCHAR(32)
);

INSERT INTO test1 (classe, sous_classe, nom) VALUES     (1, 1, 'toto'),
                                        (2, 1, 'titi');
INSERT INTO test2 (classe, sous_classe, nom) VALUES     (1, 1, 'tata'),
                                        (2, 1, 'tutu');
                                       
CREATE OR REPLACE FUNCTION concatener (IN sous_classe INTEGER) RETURNS VARCHAR AS $$
DECLARE
v_test1    VARCHAR(32);
v_test2    VARCHAR(32);
BEGIN
    SELECT        nom INTO STRICT v_test1
        FROM    test1
        WHERE    test1.sous_classe = $1;
    SELECT        nom INTO STRICT v_test2
        FROM    test2
        WHERE    test2.sous_classe = $1;
   
    RETURN v_test1 || v_test2;
   
    EXCEPTION
        WHEN TOO_MANY_ROWS THEN
            RAISE EXCEPTION 'erreur de conception dans la base';
END;
$$ LANGUAGE PLPGSQL;

Cela fonctionne bien. En lançant     select concatener(1);     il m'affiche bien     ERREUR:  erreur de conception dans la base


Ma question : est-il possible d'affiner le code pour savoir si l'erreur s'est produite dans la 1ère requête (celle sur la table test1) ou la seconde (sur la table test2).

En gros, d'avoir une fonction un peu comme suit :

CREATE OR REPLACE FUNCTION concatener (IN sous_classe INTEGER) RETURNS VARCHAR AS $$
DECLARE
v_test1    VARCHAR(32);
v_test2    VARCHAR(32);
BEGIN
    SELECT        nom INTO STRICT v_test1
        FROM    test1
        WHERE    test1.sous_classe = $1;
    SELECT        nom INTO STRICT v_test2
        FROM    test2
        WHERE    test2.sous_classe = $1;
   
    RETURN v_test1 || v_test2;
   
    EXCEPTION
        WHEN TOO_MANY_ROWS (dans premiere requete) THEN
            RAISE EXCEPTION 'erreur de conception dans la base dans la table test1';
        WHEN TOO_MANY_ROWS (dans deuxieme requete) THEN
            RAISE EXCEPTION 'erreur de conception dans la base dans la table test2';
END;
$$ LANGUAGE PLPGSQL;


Possible ? Pas possible ?

Hors ligne

#2 05/06/2011 17:31:10

Marc Cousin
Membre

Re : affinage de la section EXCEPTION d'une fonction PL/pgSQL

On peut faire ça avec 2 blocs distincts. Quelque chose du genre:

CREATE OR REPLACE FUNCTION concatener (IN sous_classe INTEGER) RETURNS VARCHAR AS $$
DECLARE
v_test1    VARCHAR(32);
v_test2    VARCHAR(32);
BEGIN
    BEGIN
      SELECT        nom INTO STRICT v_test1
          FROM    test1
         WHERE    test1.sous_classe = $1;
    EXCEPTION
        WHEN TOO_MANY_ROWS (dans premiere requete) THEN
            RAISE EXCEPTION 'erreur de conception dans la base dans la table test1';     
    END;
    BEGIN
      SELECT        nom INTO STRICT v_test2
          FROM    test2
          WHERE    test2.sous_classe = $1;
   EXCEPTION
        WHEN TOO_MANY_ROWS (dans deuxieme requete) THEN
            RAISE EXCEPTION 'erreur de conception dans la base dans la table test2';
    RETURN v_test1 || v_test2;
    END;
END;
$$ LANGUAGE PLPGSQL;

Ça a un défaut: on a deux sous-transactions (une par sous-bloc begin-end), ce qui a un coût non négligeable (à mesurer).


Marc.

Hors ligne

#3 05/06/2011 17:34:54

bebert73
Membre

Re : affinage de la section EXCEPTION d'une fonction PL/pgSQL

ah bah oui, des sous-blocs, fallait y penser. merci !!!

Hors ligne

Pied de page des forums