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

#1 13/04/2012 17:32:35

mystikilla
Membre

Procédure avec utilisation de WITH

Bonjour,

J'ai une requête utilisant WITH qui fonctionne (elle me retourne bien les résultat attendus) par contre lorsque
je me sers de cette même requête dans une procédure, l'appel de ma procédure ne me renvoie rien...

Y a t-il un lien avec le fait que WITH génère des tables 'temporaires' ?

Merci d'avance

Hors ligne

#2 13/04/2012 17:43:13

gleu
Administrateur

Re : Procédure avec utilisation de WITH

WITH ne génère pas de tables temporaires. Voyez ça plutôt comme une facilité d'écriture de la requête. Concernant votre procédure stockée, je ne vois pas de lien possible. Fournir le code de votre procédure pourrait aider.


Guillaume.

Hors ligne

#3 13/04/2012 17:57:18

mystikilla
Membre

Re : Procédure avec utilisation de WITH

Par exemple ma requete (simplifiée) :

WITH     tmp_table1 AS    (
                SELECT idauge
                FROM auges a
                WHERE idtypeauge=1
                ORDER BY idauge
            ),
    tmp_table2 AS    (
                SELECT idauge
                FROM auges
                where idauge not in (select idauge from tmp_table1)
                ORDER BY idauge
            )
SELECT idauge FROM tmp_table2

Cette requête renvoi une vingtaine d'enregistrements. Je l’insère dans une procédure :

CREATE OR REPLACE FUNCTION test(OUT idauge integer)
  RETURNS SETOF record AS
$BODY$
DECLARE
    rec record;
BEGIN
    FOR rec IN (
        WITH     tmp_table1 AS    (
                    SELECT idauge
                    FROM auges a
                    WHERE idtypeauge=1
                    ORDER BY idauge
                ),
        tmp_table2 AS    (
                    SELECT idauge
                    FROM auges
                    where idauge not in (select idauge from tmp_table1)
                    ORDER BY idauge
                )
        SELECT idauge FROM tmp_table2)
    LOOP
        idauge := rec.idauge;
        RETURN NEXT;
    END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION test OWNER TO xxx;

Mais l'appel à cette procédure ne me renvoie pas mes enregistrement contrairement à des procédure similaire mais sans le WITH...

Hors ligne

#4 13/04/2012 18:28:01

meles
Membre

Re : Procédure avec utilisation de WITH

mystikilla a écrit :

WITH     tmp_table1 AS    (
                SELECT idauge
                FROM auges a
                WHERE idtypeauge=1
                ORDER BY idauge
            ),
    tmp_table2 AS    (
                SELECT idauge
                FROM auges
                where idauge not in (select idauge from tmp_table1)
                ORDER BY idauge
            )
SELECT idauge FROM tmp_table2

la requête ne pourrait elle pas être plus simple :

WITH tmp_table AS ( 
  SELECT idauge
  FROM auges 
  WHERE idtypeauge!=1
  ORDER BY idauge
)

ou être faite avec une une opération ensembliste ?

WITH tmp_table AS ( 
  SELECT idauge
  FROM auges 
 ORDER BY 1
 EXCEPT
 SELECT idauge
  FROM auges 
 WHERE idtypeauge = 1
)

Cordialement

Hors ligne

#5 13/04/2012 18:39:19

mystikilla
Membre

Re : Procédure avec utilisation de WITH

Je suis totalement  d'accord pour la requete, je l'ai donnée à titre d'exemple.
Ce qui ne fonctionne pas, c'est son appel avec la procédure...

Hors ligne

#6 13/04/2012 21:18:53

dverite
Membre

Re : Procédure avec utilisation de WITH

C'est dû potentiellement à l'erreur classique du paramètre de fonction qui a le même nom qu'une colonne utilisée dans la requête. (ici idauge)
Essaie en changeant le nom du paramètre.

Hors ligne

#7 14/04/2012 09:42:15

edlm
Membre

Re : Procédure avec utilisation de WITH

Cette requête renvoi une vingtaine d'enregistrements. Je l’insère dans une procédure :

CREATE OR REPLACE FUNCTION test(OUT idauge integer)
  RETURNS SETOF record AS
...

il me semble qu'il y a une anomalie entre le fait de déclarer idauge comme paramètre de sortie
puis d'indiquer que la fonction retourne un SETOF record.


Le RETURNS ne devrait-il pas être RETURNS SETOF integer ?


Éric

Hors ligne

#8 14/04/2012 11:51:18

gleu
Administrateur

Re : Procédure avec utilisation de WITH

Si, tout à fait. Tenter de créer une fonction ainsi donne l'erreur suivante : ERROR:  function result type must be integer because of OUT parameters

record serait utilisable s'il y avait au moins deux éléments à renvoyer.

Pour revenir à la question initiale, il est possible d'imbriquer un WITH dans une procédure stockée :

b1=# CREATE OR REPLACE FUNCTION public.f1(OUT id integer)
 RETURNS SETOF integer
 LANGUAGE plpgsql
AS $function$
DECLARE
  rec record;
BEGIN
FOR rec IN
WITH a(toto) AS (VALUES(1), (2))
SELECT * FROM a
LOOP
  id := rec.toto;
  return next;
END LOOP;
END
$function$;
CREATE FUNCTION
b1=# SELECT * FROM f1();
 id 
----
  1
  2
(2 rows)

Donc il y a un soucis avec la façon dont la fonction est crée ou exécutée. Difficile de répondre plus précisément sans avoir le code réel de la fonction, les messages d'erreur affichés par PostgreSQL (et la version de PostgreSQL serait un plus évident).


Guillaume.

Hors ligne

#9 16/04/2012 10:18:08

mystikilla
Membre

Re : Procédure avec utilisation de WITH

dverite a écrit :

C'est dû potentiellement à l'erreur classique du paramètre de fonction qui a le même nom qu'une colonne utilisée dans la requête. (ici idauge)
Essaie en changeant le nom du paramètre.

J'ai fais le test, ca marche !!
Merci beaucoup, je m'attendais a tout sauf à ça !!! ...
J'ai beaucoup d'autres procédures ou c'est la cas et elles fonctionnent trés bien! Les mystères de l'informatique parfois! wink

Hors ligne

Pied de page des forums