Les boucles imbriquées, c’est quand tu fais tourner une boucle à l’intérieur d’une autre. Imagine une session de questions lors d’un entretien, où chaque question en amène d’autres, plus précises. La logique des boucles imbriquées, c’est ça : la boucle extérieure fait une itération, et la boucle intérieure fait ses passages pour chaque itération de la boucle extérieure.
Exemple : table de multiplication
On va écrire une fonction qui crée une table de multiplication pour les nombres de 1 à 5. C’est l’exemple classique où on utilise des boucles imbriquées :
CREATE OR REPLACE FUNCTION generate_multiplication_table()
RETURNS VOID AS $$
BEGIN
FOR i IN 1..5 LOOP -- Boucle extérieure
FOR j IN 1..5 LOOP -- Boucle intérieure
RAISE NOTICE '% x % = %', i, j, i * j; -- On log le résultat
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- Appel de la fonction :
SELECT generate_multiplication_table();
Logique de fonctionnement :
- La boucle extérieure prend les valeurs de
ide 1 à 5. - Pour chaque valeur de
i, la boucle intérieure prend les valeurs dejde 1 à 5. - À chaque étape, on combine les valeurs de
ietjpour calculer le résultat de la multiplication. - Le résultat s’affiche comme une mini-table :
1 x 1 = 1
1 x 2 = 2
...
5 x 5 = 25
Pratique : trouver les intersections dans deux tables
Maintenant, on va faire un exemple plus "dans la vraie vie". Imagine qu’on a deux tables :
students(étudiants, leurs noms),courses(cours auxquels ils sont inscrits).
On veut trouver les étudiants qui sont inscrits à plus d’un cours. On va utiliser des boucles imbriquées :
CREATE OR REPLACE FUNCTION find_students_with_multiple_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
FOR student IN SELECT DISTINCT student_name FROM students LOOP
FOR course IN SELECT DISTINCT course_name FROM courses WHERE student_id = student.student_id LOOP
RETURN QUERY SELECT student.student_name, course.course_name;
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- Appel de la fonction :
SELECT * FROM find_students_with_multiple_courses();
Récursivité
La récursivité, c’est quand une fonction s’appelle elle-même. C’est comme si tu demandais à un pote de t’expliquer SQL, et il te disait de lire la doc qui renvoie vers ce même cours… Faut pas confondre la récursivité avec une boucle infinie. La récursivité a toujours une "condition d’arrêt" (le moment où la fonction arrête de s’appeler elle-même).
Exemple : calcul de la factorielle d’un nombre
La factorielle d’un nombre n, c’est le produit de tous les nombres de 1 à n. Par exemple, la factorielle de 5 (notée 5!) vaut 5 * 4 * 3 * 2 * 1 = 120. Voilà comment on peut faire ça en récursif :
CREATE OR REPLACE FUNCTION calculate_factorial(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
-- Condition d’arrêt : la factorielle de 0 ou 1 vaut 1
IF n = 0 OR n = 1 THEN
RETURN 1;
END IF;
-- Appel récursif de la fonction
RETURN n * calculate_factorial(n - 1);
END;
$$ LANGUAGE plpgsql;
-- Appel de la fonction :
SELECT calculate_factorial(5); -- Résultat : 120
Logique de fonctionnement :
- Si
nvaut 0 ou 1, on retourne 1. - Si
n > 1, la fonction s’appelle elle-même avecn - 1et multiplie ce résultat parn. - Du coup, les appels "s’accumulent", puis se résolvent dans l’autre sens.
Exemple pratique : les nombres de Fibonacci
Les nombres de Fibonacci, c’est une suite où chaque nombre est la somme des deux précédents. Ça commence comme ça : 0, 1, 1, 2, 3, 5, 8....
On va écrire une fonction pour calculer le n-ième nombre de la suite :
CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
-- Condition d’arrêt : les deux premiers nombres sont connus
IF n = 0 THEN
RETURN 0;
ELSIF n = 1 THEN
RETURN 1;
END IF;
-- Appel récursif de la fonction
RETURN fibonacci(n - 1) + fibonacci(n - 2);
END;
$$ LANGUAGE plpgsql;
-- Appel de la fonction :
SELECT fibonacci(6); -- Résultat : 8
Quand utiliser les boucles imbriquées et la récursivité ?
Les boucles imbriquées sont top pour bosser avec des tables :
- Comparer des valeurs entre deux tables.
- Construire des combinaisons de données complexes.
La récursivité, c’est mieux pour :
- Calculer des suites (genre factorielle, Fibonacci).
- Travailler avec des structures hiérarchiques (genre un arbre de catégories de produits).
Erreurs classiques
Les boucles imbriquées peuvent parfois coûter cher niveau perf, surtout avec de grosses tables. Utilise-les seulement si tu ne peux pas faire autrement avec du SQL classique.
Quand tu utilises la récursivité, assure-toi d’avoir une vraie "condition d’arrêt". Sinon tu vas te retrouver avec un appel infini de la fonction et sûrement une erreur de stack overflow.
Les constructions imbriquées compliquées peuvent rendre le debug galère. Aide-toi de RAISE NOTICE pour afficher des résultats intermédiaires.
GO TO FULL VERSION