Parfois, tout se passe comme prévu dans une boucle — jusqu'à ce qu'il y ait une raison de s'arrêter plus tôt. Heureusement, PL/pgSQL nous file des outils bien pratiques pour gérer ça.
Interrompre une boucle avec EXIT
Il arrive qu'on doive terminer une boucle avant qu'elle n'arrive à sa fin toute seule. Par exemple, quand on trouve la valeur qu'on cherchait, qu'on détecte une erreur ou qu'on veut arrêter selon une condition. Dans ces cas-là, on utilise EXIT.
EXIT, c'est comme dire à la boucle : "C'est bon, t'as fait le taf, on arrête là".
La syntaxe de EXIT est ultra simple :
EXIT WHEN condition;
Ici, le mot-clé WHEN précise sous quelle condition la boucle va s'arrêter. Si tu ne mets pas de condition, EXIT arrête direct la boucle en cours.
Exemple : arrêter la boucle quand on trouve une valeur précise
Imaginons qu'on a une colonne avec les numéros des étudiants, et qu'on veut trouver l'étudiant avec un identifiant précis. Dès qu'on le trouve, on arrête la boucle.
DO $$
DECLARE
student_id INT;
BEGIN
FOR student_id IN 1..100 LOOP
RAISE NOTICE 'Vérification de l''ID étudiant : %', student_id;
-- Si on a trouvé le bon étudiant, on arrête la boucle
IF student_id = 42 THEN
RAISE NOTICE 'Étudiant avec l''ID 42 trouvé !';
EXIT;
END IF;
END LOOP;
END $$;
Dans cet exemple, la boucle parcourt les nombres de 1 à 100, en vérifiant chaque "étudiant". Dès que l'ID 42 est trouvé, on affiche un message et on arrête la boucle.
Sauter une itération avec CONTINUE
Il y a des moments où, dans une boucle, tu veux zapper certaines itérations, mais continuer avec la suivante. C'est super utile si tu veux ignorer des données "inutiles" ou sauter des étapes pour des cas particuliers.
CONTINUE dit : "OK, cette condition ne nous va pas, on passe à l'itération suivante".
CONTINUE fonctionne comme EXIT, sauf qu'au lieu d'arrêter la boucle, il saute juste l'itération en cours :
CONTINUE WHEN condition;
Si la condition est vraie, l'itération actuelle s'arrête et on passe à la suivante.
Exemple : sauter les nombres pairs
Dans cet exemple, on va parcourir les nombres de 1 à 10, mais ignorer les nombres pairs et afficher seulement les impairs.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..10 LOOP
-- On saute les nombres pairs
IF num % 2 = 0 THEN
CONTINUE;
END IF;
RAISE NOTICE 'Nombre impair : %', num;
END LOOP;
END $$;
Ici, CONTINUE saute toutes les itérations où num % 2 = 0 (donc quand le nombre est pair). Résultat : seuls les nombres impairs s'affichent dans le log.
Combiner EXIT et CONTINUE
Tu peux utiliser EXIT et CONTINUE ensemble pour gérer ta boucle de façon plus flexible. Par exemple, tu peux sauter les itérations inutiles avec CONTINUE, mais arrêter toute la boucle si tu trouves un truc important.
Voilà un exemple où on saute tous les nombres multiples de 3, mais on arrête la boucle dès qu'on atteint le nombre 15.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..20 LOOP
-- On saute les nombres multiples de 3
IF num % 3 = 0 THEN
CONTINUE;
END IF;
-- On arrête la boucle si le nombre vaut 15
IF num = 15 THEN
RAISE NOTICE 'On s''arrête au nombre %', num;
EXIT;
END IF;
RAISE NOTICE 'Nombre actuel : %', num;
END LOOP;
END $$;
Voilà comment la boucle fonctionne ici :
- Les nombres multiples de 3 sont sautés (
CONTINUE). - Si le nombre vaut 15, la boucle s'arrête (
EXIT). - Les autres nombres sont affichés.
Exemple avancé : sauter les données incorrectes et arrêter en cas d'erreur critique
Maintenant, imaginons un cas plus réaliste. On veut traiter une liste d'étudiants en vérifiant leurs données. Les enregistrements incorrects seront sautés, et en cas "d'erreur critique", on arrête tout.
DO $$
DECLARE
student RECORD;
BEGIN
FOR student IN
SELECT * FROM students
LOOP
-- On saute les enregistrements avec des données incorrectes
IF student.name IS NULL THEN
RAISE NOTICE 'On saute l''étudiant avec l''ID % : nom manquant', student.id;
CONTINUE;
END IF;
-- On arrête la boucle en cas d'erreur critique
IF student.status = 'ERROR' THEN
RAISE EXCEPTION 'Erreur critique pour l''ID étudiant %', student.id;
EXIT; -- Cette ligne est en fait superflue, car RAISE EXCEPTION arrête déjà l'exécution.
END IF;
-- Traitement de l'enregistrement
RAISE NOTICE 'Traitement de l''étudiant : %', student.name;
END LOOP;
END $$;
Dans cet exemple, CONTINUE sert à sauter les étudiants sans nom, et EXIT (avec RAISE EXCEPTION) arrête la boucle si on tombe sur une grosse erreur.
Conseils pratiques et erreurs classiques
Fais gaffe à la logique de tes conditions. Mal utiliser les expressions conditionnelles dans EXIT WHEN ou CONTINUE WHEN peut donner des résultats chelous. Par exemple, la boucle peut s'arrêter trop tôt ou zapper des données importantes.
Ne bourre pas ton code de CONTINUE. Si ton code est blindé de vérifs avec CONTINUE, c'est peut-être le moment de revoir la logique de ta boucle pour la simplifier.
Ne confonds pas EXIT et RETURN. EXIT arrête juste la boucle en cours, alors que RETURN stoppe toute la fonction.
Attention aux boucles infinies. Si tu utilises une boucle LOOP sans condition d'arrêt claire, oublie de mettre un EXIT et ta boucle va tourner à l'infini.
GO TO FULL VERSION