CodeGym /Cours /SQL SELF /Comment renvoyer des valeurs depuis des fonctions en PL/p...

Comment renvoyer des valeurs depuis des fonctions en PL/pgSQL

SQL SELF
Niveau 50 , Leçon 1
Disponible

Quand tu écris des fonctions dans PostgreSQL, une des premières questions c’est de piger comment renvoyer un résultat. Parfois tu veux juste renvoyer un nombre. Parfois — une table entière. Et parfois même plusieurs ensembles de données. Dans cette partie, on va voir tous les cas de base : du plus simple RETURN à RETURN QUERY, RETURNS TABLE et SETOF.

Un seul résultat : RETURN

Si ta fonction doit juste renvoyer une seule valeur — genre une somme ou le nombre de lignes — utilise simplement RETURN.

CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
    total INT;
BEGIN
    SELECT COUNT(*) INTO total FROM students;
    RETURN total;
END;
$$ LANGUAGE plpgsql;

Quand tu crées une fonction en PL/pgSQL, tu dois préciser ce qu’elle renvoie. Ça se fait avec le mot-clé RETURNS, qui définit le "format" du résultat que la fonction va rendre. Donc si tu veux renvoyer un nombre, un texte ou une table de données — tout ça doit être écrit dans la ligne avec RETURNS.

Un exemple tout simple :

CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
    RETURN a + b;
END;
$$ LANGUAGE plpgsql;

Ici, le mot-clé RETURNS INT indique que la fonction renvoie un nombre.

Retourner une seule valeur

On commence par le plus simple — une fonction qui renvoie une seule valeur. Par exemple, une fonction qui compte le nombre d’étudiants dans la table students :

CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
    total INT;
BEGIN
    SELECT COUNT(*) INTO total FROM students; -- On stocke le résultat de la requête dans la variable total
    RETURN total; -- On renvoie le résultat
END;
$$ LANGUAGE plpgsql;

Maintenant, on peut appeler cette fonction :

SELECT count_students(); -- Va renvoyer le nombre d’étudiants

Retourner plusieurs valeurs avec RETURNS TABLE

Parfois, tu veux renvoyer non pas une seule valeur, mais tout un ensemble d’enregistrements. Genre la liste de tous les étudiants avec leurs noms et identifiants. Pour ça, on utilise la construction RETURNS TABLE.

CREATE FUNCTION get_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY SELECT id, name FROM students; -- On renvoie le résultat de la requête comme une table
END;
$$ LANGUAGE plpgsql;

Maintenant, on peut appeler cette fonction :

SELECT * FROM get_students(); -- Va renvoyer la table avec tous les étudiants

Fais gaffe aux mots-clés RETURNS TABLE. Ça indique que la fonction renvoie une table avec les colonnes précisées (id et name ici).

Utilisation de RETURN QUERY

Tu dois déjà kiffer notre exemple ci-dessus. Mais voilà un détail en plus : RETURN QUERY — c’est la baguette magique de PL/pgSQL qui permet de renvoyer direct les données d’une requête. Avec ça, tu peux renvoyer le résultat d’une requête entière ou juste une partie.

Imaginons qu’on veuille renvoyer tous les étudiants qui sont actifs (leur statut dans la base est active = TRUE) :

CREATE FUNCTION get_active_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT id, name
    FROM students
    WHERE active = TRUE; -- On renvoie seulement les étudiants actifs
END;
$$ LANGUAGE plpgsql;

Maintenant, on peut appeler la fonction et choper les données des étudiants actifs :

SELECT * FROM get_active_students();

Retourner plusieurs lignes sans RETURNS TABLE

Dans certains cas, tu peux vouloir renvoyer des lignes de données sans utiliser RETURNS TABLE. Pour ça, tu peux utiliser le type SETOF. Ça permet de renvoyer des lignes de la même structure. Par exemple :

CREATE FUNCTION get_student_names() RETURNS SETOF TEXT AS $$
BEGIN
    RETURN QUERY
    SELECT name
    FROM students;
END;
$$ LANGUAGE plpgsql;

Cette fonction renvoie juste la liste des prénoms des étudiants :

SELECT * FROM get_student_names();

Retourner des valeurs selon les paramètres d’entrée

Les fonctions ne renvoient pas toujours que des résultats statiques. Elles peuvent utiliser des paramètres pour changer dynamiquement les résultats.

Voilà un exemple pour renvoyer les données selon l’identifiant de l’étudiant

CREATE FUNCTION get_student_by_id(student_id INT) RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT id, name
    FROM students
    WHERE id = student_id; -- On utilise le paramètre student_id
END;
$$ LANGUAGE plpgsql;

Maintenant tu peux demander les infos d’un étudiant précis :

SELECT * FROM get_student_by_id(3); -- Va renvoyer les données de l’étudiant avec ID = 3

Retourner des données complexes (plusieurs ensembles)

Parfois, les données sont tellement complexes qu’il faut les renvoyer en plusieurs ensembles. Pour ça, tu peux utiliser des curseurs. Par exemple, si tu veux fournir deux ensembles de données depuis une fonction — la liste des étudiants actifs et celle des inactifs.

CREATE FUNCTION get_students_status() RETURNS SETOF RECORD AS $$
BEGIN
    RETURN QUERY
    SELECT id, name, 'actif' AS status
    FROM students
    WHERE active = TRUE;

    RETURN QUERY
    SELECT id, name, 'inactif' AS status
    FROM students
    WHERE active = FALSE;
END;
$$ LANGUAGE plpgsql;

Maintenant tu peux récupérer les deux ensembles de données :

SELECT * FROM get_students_status();

Erreurs classiques avec RETURNS

Oublier de préciser le type de retour : Si tu ne précises pas ce que la fonction renvoie, PostgreSQL va râler. Par exemple :

CREATE FUNCTION no_return_type() AS $$ -- Erreur, RETURNS non précisé
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

Types de données qui ne correspondent pas : vérifie bien que les valeurs renvoyées correspondent aux types déclarés. Par exemple, si tu as mis INT, ne tente pas de renvoyer une chaîne de caractères.

Oubli de RETURN QUERY : si tu oublies d’utiliser RETURN QUERY pour une requête complexe, la fonction ne renverra rien du tout.

Retour incorrect de plusieurs valeurs : si tu renvoies une ligne de données mais que tu oublies d’utiliser SETOF ou TABLE, PostgreSQL va te sortir une erreur.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION