A volte in un ciclo tutto fila liscio... finché non spunta un motivo per fermarsi prima. Per fortuna, PL/pgSQL ci dà strumenti comodi per gestire questa cosa.
Interrompere un ciclo con EXIT
Capita che bisogna terminare un ciclo prima che finisca da solo. Magari perché hai trovato il valore che cercavi, hai beccato un errore o hai raggiunto una certa condizione. In questi casi usiamo EXIT.
EXIT è il modo per "dire" al ciclo: "Basta così, hai fatto il tuo, ora stop".
La sintassi di EXIT è super semplice:
EXIT WHEN condizione;
Qui la parola chiave WHEN indica quando il ciclo deve essere interrotto. Se non metti la condizione, EXIT chiude subito il ciclo corrente.
Esempio: terminare il ciclo quando trovi il valore giusto
Supponiamo di avere una colonna con i numeri degli studenti e vogliamo trovare lo studente con un certo ID. Appena lo troviamo, il ciclo deve finire.
DO $$
DECLARE
student_id INT;
BEGIN
FOR student_id IN 1..100 LOOP
RAISE NOTICE 'Sto controllando lo studente ID: %', student_id;
-- Se troviamo lo studente giusto, chiudiamo il ciclo
IF student_id = 42 THEN
RAISE NOTICE 'Studente con ID 42 trovato!';
EXIT;
END IF;
END LOOP;
END $$;
In questo esempio il ciclo scorre i numeri da 1 a 100, controllando ogni "studente". Appena trova l'ID 42, stampa il messaggio e termina il ciclo.
Saltare un'iterazione con CONTINUE
Capita che dentro un ciclo vuoi saltare certe iterazioni, ma continuare con la prossima. È utile se vuoi ignorare dati "inutili" o saltare passi per condizioni particolari.
CONTINUE dice: "Ok, questa condizione non ci va bene, passiamo direttamente alla prossima iterazione".
CONTINUE funziona come EXIT, solo che invece di chiudere il ciclo, salta l'iterazione corrente:
CONTINUE WHEN condizione;
Se la condizione è vera, l'iterazione attuale si chiude e si passa subito alla prossima.
Esempio: saltare i numeri pari
In questo esempio scorriamo i numeri da 1 a 10, ma ignoriamo quelli pari e stampiamo solo i dispari.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..10 LOOP
-- Saltiamo i numeri pari
IF num % 2 = 0 THEN
CONTINUE;
END IF;
RAISE NOTICE 'Numero dispari: %', num;
END LOOP;
END $$;
Qui CONTINUE salta tutte le iterazioni dove num % 2 = 0 (cioè il numero è pari). Quindi nel log vedrai solo i numeri dispari.
Combinare EXIT e CONTINUE
EXIT e CONTINUE si possono usare insieme per gestire il ciclo in modo più flessibile. Per esempio, puoi saltare le iterazioni inutili con CONTINUE, ma chiudere tutto il ciclo se trovi qualcosa di importante.
Ecco un esempio dove saltiamo tutti i numeri multipli di 3, ma chiudiamo il ciclo appena arriviamo al numero 15.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..20 LOOP
-- Saltiamo i numeri multipli di 3
IF num % 3 = 0 THEN
CONTINUE;
END IF;
-- Chiudiamo il ciclo se il numero è 15
IF num = 15 THEN
RAISE NOTICE 'Mi fermo al numero %', num;
EXIT;
END IF;
RAISE NOTICE 'Numero attuale: %', num;
END LOOP;
END $$;
Qui il ciclo funziona così:
- I numeri multipli di 3 vengono saltati (
CONTINUE). - Se il numero è 15, il ciclo si ferma (
EXIT). - Tutti gli altri numeri vengono stampati.
Esempio avanzato: saltare dati non validi e fermarsi su errore critico
Ora immaginiamo un caso più reale. Vogliamo processare una lista di studenti, controllando i loro dati. Le registrazioni non valide le saltiamo, ma in caso di "errore critico" fermiamo tutto.
DO $$
DECLARE
student RECORD;
BEGIN
FOR student IN
SELECT * FROM students
LOOP
-- Saltiamo le registrazioni con dati non validi
IF student.name IS NULL THEN
RAISE NOTICE 'Salto lo studente con ID %: Nome mancante', student.id;
CONTINUE;
END IF;
-- Fermiamo il ciclo su errore critico
IF student.status = 'ERRORE' THEN
RAISE EXCEPTION 'Errore critico per lo studente ID %', student.id;
EXIT; -- Questa riga in realtà è superflua, perché RAISE EXCEPTION ferma tutto.
END IF;
-- Elaborazione della registrazione
RAISE NOTICE 'Sto processando lo studente: %', student.name;
END LOOP;
END $$;
In questo esempio CONTINUE serve per saltare gli studenti senza nome, mentre EXIT (insieme a RAISE EXCEPTION) ferma tutto se c'è un errore serio.
Consigli pratici ed errori tipici
Non dimenticare la logica delle condizioni. Usare male le condizioni dentro EXIT WHEN o CONTINUE WHEN può portare a comportamenti strani. Tipo che il ciclo si ferma troppo presto o salta dati importanti.
Non esagerare con CONTINUE. Se il tuo codice è pieno di controlli con CONTINUE, forse è il caso di rivedere la logica del ciclo per semplificarla.
Non confondere EXIT e RETURN. EXIT chiude solo il ciclo corrente, mentre RETURN termina tutta la funzione.
Occhio ai cicli infiniti. Se usi un ciclo LOOP senza una condizione chiara di uscita, ti dimentichi di EXIT e il ciclo va avanti all'infinito.
GO TO FULL VERSION