IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

plpgsql retournant un tableau = probleme


Sujet :

PostgreSQL

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut plpgsql retournant un tableau = probleme
    Bonjour.

    Pour simplifier mon probleme, disons que je tente de créer une fonction qui fasse une requette et me retourne le resultat. (evidemment c'est plus compliqué que ca en vrai)

    En me basant sur les docs trouvées, ma fonction retourne un record. Mais ca ne me va pas du tout, car ce qui m'est retourné n'a qu'une seule colonne contenant le record, du coup, mon client derriere ne sait pas lire le resultat. Or moi je voudrais récupérer les lignes de mon tableau intégralement !!!

    Je suis programmeur, pas DBA aussi désolé si ma question semble stupide...

    Lorsque j'appelle ma fonction, je voudrais que ce soit comme ci je faisais cette requette (XXX etant la valeur de mon argument) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM employe WHERE employe.id = XXX;
    Et voici ma fonction actuelle qui ne va pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE OR REPLACE FUNCTION "GetEmploye"(userid integer)
      RETURNS record AS
    $BODY$
    DECLARE
       rec record;
    BEGIN
       SELECT * FROM employe  WHERE  employe.id  =userid INTO rec;              
       return rec;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    Auriez vous un lien/exemple pour me montrer le plus simplement du monde, comme on parlerait à un petit enfant, comment atteindre l'objectif?

    Un grand merci d'avance.

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    J'ai fini par hasard, à tomber sur la réponse :

    Ceci me retournera bien le meme type que si je faisais un simple select :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE OR REPLACE FUNCTION "GetEmploye"(userid integer)
      RETURNS employe AS
    $BODY$
    DECLARE
       rec employe%ROWTYPE;
    BEGIN
       SELECT * FROM employe  WHERE  employe.id  =userid INTO rec;              
       RETURN rec;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Anciennement flaggé "resolu" je réouvre le dossier car la méthode employé pose un nouveau probleme.

    Si la requette ne trouve pas de résultat, ma fonction ne retourne pas un resultat "null" mais une ligne vide !

    Exemple avec un userid qui ne mene nullepart :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT count(*) FROM "GetEmploye"(123)
    va me retourner 1 alors que l'employe 123 n'existe pas !

    En somme ce que j'aimerai, c'est que ma fonctionne simule rigoureusement le comportement d'une requette. J'ai du mal a comprendre pourquoi les choses se compliquent de la sorte...

    J'ai biensur modifié ma fonction pour qu'elle retourne un null si elle ne trouve pas de résultat, mais ca ne change rien au probleme.

    Comment faire SVP ?

  4. #4
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 476
    Points : 831
    Points
    831
    Par défaut
    bonjour,
    peut-être en rajoutant une condition

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    BEGIN
    if userid in select id from employe then
       SELECT * FROM employe  WHERE  employe.id  =userid INTO rec;              
       RETURN rec;
    end if;

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 934
    Points : 4 347
    Points
    4 347
    Par défaut
    Après un SELECT, NOT FOUND sera vrai s'il n'y a pas de résultat, donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    selectif not found then
     -- no record found: return null, raise an exception, …
    else
     ...
    end;

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par giova_fr Voir le message
    En somme ce que j'aimerai, c'est que ma fonctionne simule rigoureusement le comportement d'une requette. J'ai du mal a comprendre pourquoi les choses se compliquent de la sorte...

    J'ai biensur modifié ma fonction pour qu'elle retourne un null si elle ne trouve pas de résultat, mais ca ne change rien au probleme.

    Comment faire SVP ?
    C'est parce que retourner un enregistrement null n'est pas la même chose que de ne rien retourner du tout.
    Mais le plus simple ici serait d'utiliser RETURN QUERY qui est pile fait pour ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     RETURN QUERY SELECT * FROM employe  WHERE  employe.id  =userid;
    Sinon pour ce genre de fonction mono-instruction, on utilise généralement le langage sql plutôt que plpgsql car il n'y a rien de procédural, exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    create function getemp(int) returns emp as 'select * from emp where id=$1'
     language sql;

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Merci beaucoup pour vos réponses.

    estofilo vous venez de me donner une excelente réponse, explicative et claire.

    @JeitEmgie> j'avais biensur essayé ta méthode, mais ca ne marchait pas, il me retournait quand meme une ligne vide, sans doute à cause du type de sortie de ma fonction.

    @xavier-Pierre> impossible, la fonction DOIT retourner quelque chose, sinon ca plante à l'execution, c'est ainsi...

    Ma fonction ne fait pas une simple requette, elle en fait plusieurs, et en fonction des résultats authorise ou non la requette finale qui sera retournée.

    Je n'ai d'ailleur pas encore tout à fait compris l'interret d'une fonction SQL, j'imagine pour une question de droits que je maitrise tres tres mal pour le moment, mais bon c'est un autre sujet...

    Je vais de ce pas tester return QUERY

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    arg ca se passe toujours tres mal...

    Je reprécise au passage que dans mes exemples, je simplifie ma fonction au max, n'imaginez pas qu'elle ne fasse qu'une simple requette !

    Au debut j'ai fais mon simple return Query ...
    mais le compilateur n'etait pas content, disant en gros que ma fonction doit retourner un setof :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE OR REPLACE FUNCTION "GetEmploye"(userid integer)
      RETURNS employe AS
    $BODY$
    DECLARE
       rec employe%ROWTYPE;
    BEGIN
      RETURN QUERY SELECT * FROM employe  WHERE  employe.id  =userid;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    donne

    ERROR: RETURN must specify a record or row variable in function returning tuple at or near "QUERY"
    ok ca me parait plutot logique, donc je change la signature de la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE OR REPLACE FUNCTION "GetEmploye"(userid integer)
      RETURNS SETOF employe AS
    $BODY$
    DECLARE
       rec employe%ROWTYPE;
    BEGIN
      RETURN QUERY SELECT * FROM employe  WHERE  employe.id  =userid;
    END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    Et là il me dit l'inverse on dirait, je n'y comprend rien :
    ERROR: RETURN cannot have a parameter in function returning set; use RETURN NEXT at or near "QUERY"

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    C'est quelle version de postgresql?

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    8.2.13 que je ne peux pas mettre à jour

  11. #11
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    RETURN QUERY n'existait pas encore en 8.2.

    Il faudrait donc utiliser RETURN NEXT autant de fois qu'il y a de lignes à retourner suivi de RETURN pour finir. Voir la doc plpgsql pour la version 8.2:
    http://www.postgresql.org/docs/8.2/s...ENTS-RETURNING

  12. #12
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Points : 488
    Points
    488
    Par défaut
    Ca fonctionne enfin comme voulu merci

    Je suis juste surpris de devoir encore appeller ma fonction ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM "GetEmploye"(123);
    Je m'attendais plus à devoir faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT "GetEmploye"(123);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 9
    Dernier message: 14/10/2005, 19h32
  2. Retourner un tableau ?
    Par chateau_dur dans le forum C++
    Réponses: 8
    Dernier message: 20/08/2005, 13h11
  3. retourné un tableau
    Par elekis dans le forum C++
    Réponses: 5
    Dernier message: 17/03/2005, 16h03
  4. [plpgsql] comment retourner un tableau
    Par hpghost dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 27/06/2004, 22h09
  5. Fonction qui retourne un tableau
    Par _lara_ dans le forum ASP
    Réponses: 6
    Dernier message: 24/05/2004, 16h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo