En programmation, deux trucs sont super importants : piger ce qui se passe (surtout quand tout part en vrille) et renvoyer des données utiles. C’est encore plus vrai avec PL/pgSQL, vu que tout tourne côté serveur, donc le debug, c’est pas toujours simple. Heureusement, il y a des outils intégrés pour t’aider :
RAISE NOTICE — c’est la façon d’afficher des messages pendant l’exécution d’une fonction. Imagine-le comme un console.log en JavaScript ou un print en Python. Tu peux montrer la valeur des variables, l’état actuel de l’exécution ou juste laisser un petit "coucou" pour ton toi du futur.
RETURN QUERY — c’est le moyen de renvoyer un ensemble de données, genre une table entière ou le résultat d’une requête complexe. Grâce à ça, les fonctions PL/pgSQL ressemblent à des vraies requêtes SQL.
Commande RAISE NOTICE
RAISE NOTICE permet d’afficher des messages à l’écran pendant l’exécution d’une fonction. Le format ressemble à ça :
RAISE NOTICE 'Message : %', valeur;
%— c’est un placeholder pour une variable, comme dansprintfen C.- Après le texte du message, tu peux lister les variables à insérer.
Exemple d’utilisation
Imagine que tu écris une fonction qui compte le nombre d’étudiants dans différents groupes. Tu veux voir les valeurs intermédiaires pour vérifier si tout roule.
CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
group_name TEXT;
student_count INT;
BEGIN
FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
SELECT COUNT(*) INTO student_count
FROM students WHERE group_name = group_name;
-- Affichage des résultats
RAISE NOTICE 'Groupe : %, Nombre d’étudiants : %', group_name, student_count;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Quand tu vas appeler cette fonction :
SELECT count_students_in_groups();
Tu verras des messages comme ça dans les logs :
NOTICE: Groupe : Mathématiques, Nombre d’étudiants : 30
NOTICE: Groupe : Philosophie, Nombre d’étudiants : 25
NOTICE: Groupe : Biologie, Nombre d’étudiants : 18
Remarque que la fonction ne renvoie rien (elle est créée avec RETURNS VOID), mais RAISE NOTICE te montre comment avance la boucle.
Astuces sympas avec RAISE
En plus de NOTICE, tu peux utiliser d’autres niveaux de messages :
RAISE DEBUG— pour des infos en plus (affiché seulement si le niveau de log est sur DEBUG).RAISE INFO— pour des infos générales.RAISE WARNING— pour les avertissements.RAISE EXCEPTION— pour générer des erreurs, on verra ça plus tard.
Pour le debug, le mieux c’est d’utiliser NOTICE ou DEBUG, car c’est pratique et ça n’arrête pas la fonction.
Commande RETURN QUERY : renvoie des données comme un pro
RETURN QUERY est utilisé en PL/pgSQL pour renvoyer un ensemble de lignes. Avec ça, tu peux renvoyer le résultat d’une requête SQL direct depuis une fonction. La syntaxe, c’est :
RETURN QUERY <requête SQL>;
Tu peux aussi combiner plusieurs requêtes :
RETURN QUERY <requête SQL 1>;
RETURN QUERY <requête SQL 2>;
Exemple 1 : fonction avec RETURN QUERY
On va écrire une fonction qui renvoie la liste des étudiants d’un groupe donné.
CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;
Maintenant, on appelle la fonction :
SELECT * FROM get_students_by_group('Mathématiques');
Pour tester la fonction, crée d’abord la table students et ajoute des données :
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);
INSERT INTO students (name, group_name) VALUES
('Otto Song', 'Physique'),
('Alex Lin', 'Mathématiques'),
('Anna Vel', 'Mathématiques'),
('Maria Chi', 'Histoire');
Résultat :
| id | name |
|---|---|
| 2 | Alex Lin |
| 3 | Anna Vel |
Comme tu vois, la fonction marche comme une requête SQL classique.
Exemple 2 : Combiner plusieurs requêtes
Et si on veut renvoyer des données combinées de plusieurs tables ? On va renvoyer la liste des étudiants et des cours auxquels ils sont inscrits.
CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT s.name, c.name
FROM students s
JOIN enrollments e ON s.id = e.student_id
JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;
D’abord, crée trois tables : students, courses et enrollments, puis ajoute quelques données :
-- Table des étudiants
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Table des cours
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Table des inscriptions (liaison)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);
-- Ajout des étudiants
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
-- Ajout des cours
INSERT INTO courses (name) VALUES
('Mathématiques'),
('Physique'),
('Histoire');
-- Ajout des inscriptions
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> Physique
(2, 1), -- Alex -> Mathématiques
(3, 1), -- Anna -> Mathématiques
(4, 3); -- Maria -> Histoire
Dans ce cas, l’appel de la fonction :
SELECT * FROM get_students_and_courses();
donnera ce résultat :
| student_name | course_name |
|---|---|
| Otto Song | Physique |
| Alex Lin | Mathématiques |
| Anna Vel | Mathématiques |
| Maria Chi | Histoire |
La fonction combine proprement les données des trois tables et te montre quel étudiant est inscrit à quel cours.
Combiner RAISE NOTICE et RETURN QUERY
Parfois, RETURN QUERY et RAISE NOTICE peuvent bosser ensemble dans une même fonction, pour que tu puisses suivre l’exécution et voir les résultats intermédiaires.
Voici un exemple de fonction qui renvoie des infos sur les étudiants et affiche aussi des messages pour montrer l’avancement :
CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
count_students INT;
BEGIN
-- Compter le nombre d’étudiants
SELECT COUNT(*) INTO count_students FROM students;
RAISE NOTICE 'Nombre total d’étudiants : %', count_students;
-- Renvoyer les infos sur les étudiants
RETURN QUERY
SELECT id, name FROM students;
RAISE NOTICE 'La fonction a terminé son exécution.';
END;
$$ LANGUAGE plpgsql;
Si la table students n’existe pas encore, crée-la et ajoute des données :
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');
Maintenant, en appelant la fonction :
SELECT * FROM debug_students();
Tu obtiendras à la fois les données et les messages :
| student_id | student_name |
|---|---|
| 1 | Otto Song |
| 2 | Alex Lin |
| 3 | Anna Vel |
| 4 | Maria Chi |
Affichage des messages dans la console :
NOTICE: Nombre total d’étudiants : 4
NOTICE: La fonction a terminé son exécution.
Erreurs classiques à l’utilisation
Erreur avec les variables dans RAISE NOTICE : si tu oublies de déclarer une variable ou si tu fais une faute dans son nom, tu auras une erreur variable does not exist. Vérifie toujours que tes variables sont bien déclarées.
Erreur de type de retour : si tu utilises RETURN QUERY mais que tu n’indiques pas RETURNS TABLE à la création de la fonction, PostgreSQL va râler. Assure-toi que les types de retour correspondent aux données renvoyées.
Erreur avec les placeholders dans RAISE : si le nombre de placeholders % ne correspond pas au nombre de variables, tu auras une erreur. Par exemple :
RAISE NOTICE 'Valeur : %, %', value1;
Ça va planter parce qu’il manque la deuxième variable.
GO TO FULL VERSION