A veces, en un bucle todo va según lo planeado... hasta que aparece una razón para parar antes de tiempo. Por suerte, PL/pgSQL nos da herramientas muy cómodas para manejar esto.
Interrumpir un bucle con EXIT
A veces necesitas terminar la ejecución de un bucle antes de que llegue al final por sí solo. Esto puede pasar, por ejemplo, si encuentras el valor que buscabas, detectas un error o terminas las iteraciones por alguna condición. En estos casos usamos EXIT.
EXIT es como decirle al bucle: "Ya está, hiciste tu trabajo, es hora de parar".
La sintaxis de EXIT es súper sencilla:
EXIT WHEN condición;
Aquí la palabra clave WHEN indica bajo qué condición se terminará el bucle. Si no pones ninguna condición, EXIT simplemente termina el bucle actual al instante.
Ejemplo: terminar el bucle cuando se encuentra un valor específico
Supón que tienes una columna con los números de los estudiantes y quieres encontrar a un estudiante con un identificador concreto. En cuanto lo encuentres, hay que terminar el bucle.
DO $$
DECLARE
student_id INT;
BEGIN
FOR student_id IN 1..100 LOOP
RAISE NOTICE 'Comprobando ID de estudiante: %', student_id;
-- Si encontramos el estudiante que buscamos, terminamos el bucle
IF student_id = 42 THEN
RAISE NOTICE '¡Estudiante con ID 42 encontrado!';
EXIT;
END IF;
END LOOP;
END $$;
En este ejemplo, el bucle recorre los números del 1 al 100, comprobando cada "estudiante". En cuanto encuentra el ID 42, muestra un mensaje y termina la ejecución.
Saltar una iteración con CONTINUE
Hay situaciones en las que dentro de un bucle necesitas saltar ciertas iteraciones, pero seguir con la siguiente. Esto es útil si quieres ignorar datos "innecesarios" o saltar pasos bajo condiciones específicas.
CONTINUE dice: "Vale, esta condición no nos sirve, vamos a la siguiente iteración".
CONTINUE funciona igual que EXIT, solo que en vez de terminar el bucle, salta la iteración actual:
CONTINUE WHEN condición;
Si la condición se cumple, la iteración actual termina y se pasa a la siguiente.
Ejemplo: saltar los números pares
En este ejemplo vamos a recorrer los números del 1 al 10, pero ignorando los pares y mostrando solo los impares.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..10 LOOP
-- Saltamos los números pares
IF num % 2 = 0 THEN
CONTINUE;
END IF;
RAISE NOTICE 'Número impar: %', num;
END LOOP;
END $$;
Aquí CONTINUE salta todas las iteraciones donde num % 2 = 0 (o sea, el número es par). Como resultado, en el log solo aparecen los números impares.
Combinando EXIT y CONTINUE
Puedes usar EXIT y CONTINUE juntos para controlar el bucle de forma más flexible. Por ejemplo, puedes saltar iteraciones innecesarias con CONTINUE, pero terminar el bucle si encuentras algo importante.
Aquí tienes un ejemplo donde saltamos todos los números múltiplos de 3, pero terminamos el bucle en cuanto llegamos al número 15.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..20 LOOP
-- Saltamos los números múltiplos de 3
IF num % 3 = 0 THEN
CONTINUE;
END IF;
-- Terminamos el bucle si el número es 15
IF num = 15 THEN
RAISE NOTICE 'Parando en el número %', num;
EXIT;
END IF;
RAISE NOTICE 'Número actual: %', num;
END LOOP;
END $$;
En este caso, el bucle funciona así:
- Los números múltiplos de 3 se saltan (
CONTINUE). - Si el número es 15, el bucle termina (
EXIT). - Todos los demás números se muestran.
Ejemplo avanzado: saltar datos incorrectos y terminar ante un error crítico
Ahora imagina una tarea más real. Queremos procesar una lista de estudiantes, comprobando sus datos. Las entradas incorrectas las vamos a saltar, y si hay un "error crítico", paramos el procesamiento.
DO $$
DECLARE
student RECORD;
BEGIN
FOR student IN
SELECT * FROM students
LOOP
-- Saltamos registros con datos incorrectos
IF student.name IS NULL THEN
RAISE NOTICE 'Saltando estudiante con ID %: Falta el nombre', student.id;
CONTINUE;
END IF;
-- Terminamos el bucle ante un error crítico
IF student.status = 'ERROR' THEN
RAISE EXCEPTION 'Error crítico para el estudiante con ID %', student.id;
EXIT; -- Esta línea realmente sobra, porque RAISE EXCEPTION termina la ejecución.
END IF;
-- Procesando el registro
RAISE NOTICE 'Procesando estudiante: %', student.name;
END LOOP;
END $$;
En este ejemplo, CONTINUE ayuda a saltar estudiantes sin nombre, y EXIT (junto con RAISE EXCEPTION) termina el bucle si se detecta un error grave.
Consejos prácticos y errores típicos
No te olvides de la lógica de las condiciones. Usar mal las expresiones condicionales dentro de EXIT WHEN o CONTINUE WHEN puede llevar a comportamientos inesperados. Por ejemplo, el bucle puede terminar antes de tiempo o saltar datos importantes.
No abuses de CONTINUE. Si tu código está lleno de comprobaciones con CONTINUE, igual deberías revisar la lógica del bucle para simplificarla.
No confundas EXIT y RETURN. EXIT solo termina el bucle actual, mientras que RETURN termina toda la función.
Cuidado con los bucles infinitos. Si usas un bucle LOOP sin una condición clara de salida y te olvidas de EXIT, tu bucle puede quedarse corriendo para siempre.
GO TO FULL VERSION