CodeGym /Cours /SQL SELF /Les boucles imbriquées et la récursivité

Les boucles imbriquées et la récursivité

SQL SELF
Niveau 51 , Leçon 3
Disponible

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 :

  1. La boucle extérieure prend les valeurs de i de 1 à 5.
  2. Pour chaque valeur de i, la boucle intérieure prend les valeurs de j de 1 à 5.
  3. À chaque étape, on combine les valeurs de i et j pour calculer le résultat de la multiplication.
  4. 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 :

  1. Si n vaut 0 ou 1, on retourne 1.
  2. Si n > 1, la fonction s’appelle elle-même avec n - 1 et multiplie ce résultat par n.
  3. 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é ?

  1. Les boucles imbriquées sont top pour bosser avec des tables :

    • Comparer des valeurs entre deux tables.
    • Construire des combinaisons de données complexes.
  2. 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.

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