Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#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