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 :

Utilisation des variables dans une fonction


Sujet :

PostgreSQL

  1. #1
    Membre à l'essai
    Utilisation des variables dans une fonction
    Bonjour,

    Je débute avec POSTGRESQL, et j'en suis encore aux bases.
    Et j'ai beau parcourir la doc officielle et les fora, je ne trouve nulle part la réponse à une simple question :

    Comment utilise-t-on une variable dans une requête, à l'intérieur d'une fonction?

    Je précise que je ne cherche pas à utiliser un paramètre d'entrée (dans ce cas je pourrais utiliser %1, par exemple), mais une variable que j'ai déclarée au début de ma fonction.

    Voici mon code :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE OR REPLACE FUNCTION job_check_status(job_do_id int4, job_first_status_id int4) RETURNS int4 AS '
    DECLARE
    	job_first_id int4;
    	nb_res int4;
     
    BEGIN
    	SELECT INTO job_first_id job_first FROM job_list WHERE job_id = $1;
     
    	SELECT COUNT(job_id) AS nb_res FROM job_list WHERE job_id = job_first_id AND job_status_id = $2;
     
    	RETURN nb_res;
    END;
    ' LANGUAGE plpgsql;


    Je n'arrive même pas à enregistrer ma fonction, j'ai un "Syntax error"

    Je vois bien que le problème se trouve par ici :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT COUNT(job_id) AS nb_res


    Et que j'en aurai un autre là :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    WHERE job_id = job_first_id


    Comment placer ces variables dans ma requête svp?

    Merci d'avance, c'est pénible de sécher sur un truc aussi simple et de ne pas pouvoir avancer...

  2. #2
    Membre à l'essai
    Bon, j'ai trouvé, mais cela ne m'a pas fait avancer.

    Voici comment j'ai résolu ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    DECLARE
    	job_first_id int4;
    	req text;
    	nb_res int4;
     
    BEGIN
    	SELECT INTO job_first_id job_first FROM job_list WHERE job_id = $1;
     
    	req := 'SELECT COUNT(job_id) AS nb_res FROM job_list WHERE job_id = ' || job_first_id || ' AND job_status_id = ' || $2;
    	EXECUTE req;
    RAISE NOTICE 'requete : %', req;
    	RETURN nb_res;
    END;

    Je n'ai rien changé dans la définition de ma fonction (paramètres IN et OUT).

    Le problème dans ce nouveau cas, c'est que la fonction me retourne invariablement NULL, même si un enregistrement est trouvé.

    J'ai laissé la ligne :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    RAISE NOTICE 'requete : %', req;

    pour pouvoir tester ma requête en direct, qui me renvoie bien ce que je souhaite.

    Donc là, ma variable nb_res n'est apparemment pas remplie...

    Une idée svp?

  3. #3
    Membre émérite
    La syntaxe est SELECT colonne INTO variable FROM...
    et non pas SELECT INTO variable colonne FROM...

  4. #4
    Membre régulier
    C'est peut-être pas joli / conseillé mais la clause INTO est assez tolérante.
    J'ai pour habitude de la mettre tout à la fin de mes requêtes et ça fonctionne à merveille. (Postgres 8.4)

    Pour ce qui est de ton problème je n'ai pas beaucoup d'idées.

    Selon moi
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    SELECT COUNT(job_id) FROM job_list WHERE job_id = job_first_id AND job_status_id = $2
    INTO nb_res;

    Devrait fonctionner mais je n'ai pas le temps de tester.

  5. #5
    Membre émérite
    Moi je suis bête et discipliné, je fais comme dit dans le manuel, c'est-à-dire pour un SELECT:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT select_expressions INTO [STRICT] target FROM ...;


  6. #6
    Membre à l'essai
    D'abord, merci à vous pour votre aide, et pardon pour le retard de ma réponse.

    Je ne sais pas si c'est utile de le préciser, mes fonctions utilisent le langage PL/pgSQL.
    Ca peut aider, je ne sais pas si la syntaxe diffère par rapport au langage SQL installé par défaut. C'est une contrainte de mon environnement, je dois utiliser PL/pgSQL.

    Ensuite, j'ai testé les deux cas que vous me proposez :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    req := 'SELECT COUNT(job_id) FROM job_list WHERE job_id = ' || job_first_id || ' AND job_status_id = ' || $2 || ' INTO nb_res ';

    Cela me renvoie une erreur de syntaxe :
    ERREUR: erreur de syntaxe sur ou près de « INTO »
    LINE 1: ... job_list WHERE job_id = 26 AND job_status_id = 3 INTO nb_re...

    Et :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    req := 'SELECT COUNT(job_id) INTO nb_res FROM job_list WHERE job_id = ' || job_first_id || ' AND job_status_id = ' || $2;

    Cela me renvoie une erreur :
    ERREUR: EXECUTE of SELECT ... INTO is not implemented yet

    j'ai essayé à tout hasard, d'initialiser nb_res à 0 juste avant la requête, mais j'ai la même erreur.

    Je me suis décidé à ouvrir un fil pour ça, car - ça vient sûrement de moi mais bon c'est pas glop quand même - tous les tests que je trouve dans la doc, officielle ou pas, me renvoient systématiquement bouler, avec le plus souvent, une Syntax Error.

    J'en suis donc toujours au même point : cette fonction est sensée me retourner 0 ou le nombre de lignes trouvées, mais elle me renvoie invariablement NULL.

    Donc, ma variable, que j'ai déclarée plus haut, n'est pas renseignée lorsque ma requête est exécutée. Bizarre...

    En tout cas merci

  7. #7
    Membre à l'essai
    J'ai trouvé finalement.

    Il était inutile de mettre ma requête dans une chaîne, puis d'exécuter cette chaîne. Je peux écrire directement :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT INTO nb_res COUNT(job_id) FROM job_list WHERE job_id = job_first_id  AND job_status_id = $2;


    Voici la fonction finale si ça intéresse quelqu'un :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    CREATE OR REPLACE FUNCTION job_first_status(job_do_id int4, job_first_status_id int4) RETURNS int4 AS $$
    DECLARE
    	job_first_id int4;
    	nb_res int4;
     
    BEGIN
    	-- ****************************************************
    	-- CHECK PARENT JOB STATUS
    	-- ****************************************************
    	-- Retrieve id of parent job
    	SELECT INTO job_first_id job_first FROM job_list WHERE job_id = $1;
     
    	-- check for parent job status
    	SELECT INTO nb_res COUNT(job_id) FROM job_list WHERE job_id = job_first_id  AND job_status_id =  $2;
     
    	RETURN nb_res;
    END;
    $$ LANGUAGE plpgsql;


    Merci pour vos réponses