Los bucles te permiten ejecutar un bloque de código varias veces seguidas, mientras se cumple una condición o mientras se itera sobre algún conjunto de datos. Esto es súper útil para automatizar tareas, procesar grandes volúmenes de datos o hacer operaciones repetitivas.
Imagínate que tienes que repartir caramelos a todos los niños de un grupo a mano. ¡Sería un caos! En vez de eso, puedes recorrer la lista de niños y darle un caramelo a cada uno por turno. En este escenario, "recorrer la lista" es un bucle.
En PostgreSQL hay varios tipos de bucles:
LOOP— bucle universal que se ejecuta hasta que lo pares explícitamente.FOR— bucle con un número fijo de iteraciones sobre un rango de números o el resultado de una consulta.WHILE— bucle que se ejecuta mientras la condición sea verdadera.
Vamos a ver cada tipo por separado.
Bucle infinito: LOOP
LOOP es la forma más básica de bucle en PL/pgSQL, que repite la ejecución de un bloque de código. Este bucle funciona infinitamente y tienes que terminarlo manualmente usando el comando EXIT.
Sintaxis:
LOOP
-- Tu código aquí
END LOOP;
Vamos con un ejemplo. Vamos a sumar los números del 1 al 10 usando LOOP:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
LOOP
sum := sum + counter; -- sumamos el valor actual del contador
counter := counter + 1; -- incrementamos el contador
-- Terminamos el bucle si el contador es mayor que 10
IF counter > 10 THEN
EXIT;
END IF;
END LOOP;
RAISE NOTICE 'Suma de números del 1 al 10: %', sum;
END $$;
- La variable
counterse incrementa en cada iteración. - La condición
IF counter > 10 THEN EXIT;termina el bucle cuando el contador pasa de 10. - Al final se muestra la suma de los números.
Bucle sobre un rango o conjunto de datos: FOR
El segundo tipo de bucle, FOR, se usa para iterar sobre:
- Un rango de números.
- El resultado de una consulta SQL.
Bucle sobre un rango de números
Sintaxis:
FOR variable IN [REVERSE] start..end LOOP
-- Tu código aquí
END LOOP;
Vamos a mostrar los números del 1 al 5:
DO $$
BEGIN
FOR i IN 1..5 LOOP
RAISE NOTICE 'Valor actual: %', i;
END LOOP;
END $$;
Ejemplo en orden inverso:
DO $$
BEGIN
FOR i IN REVERSE 5..1 LOOP
RAISE NOTICE 'Orden inverso: %', i;
END LOOP;
END $$;
Bucle sobre el resultado de una consulta SQL
Esta variante es útil para procesar filas de una tabla.
Sintaxis:
FOR variable IN QUERY (SELECT ...) LOOP
-- Tu código aquí
END LOOP;
Vamos con un ejemplo de iteración sobre las filas de la tabla students:
DO $$
DECLARE
student_name TEXT;
BEGIN
FOR student_name IN QUERY (SELECT name FROM students) LOOP
RAISE NOTICE '¡Hola, %!', student_name;
END LOOP;
END $$;
Bucle condicional: WHILE
WHILE se ejecuta mientras la condición dada sea verdadera.
Sintaxis:
WHILE condición LOOP
-- Tu código aquí
END LOOP;
Vamos a sumar los números del 1 al 10 usando WHILE:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
WHILE counter <= 10 LOOP
sum := sum + counter;
counter := counter + 1;
END LOOP;
RAISE NOTICE 'Suma de números del 1 al 10: %', sum;
END $$;
Ejemplos de la vida real
Ahora que ya tenemos claro lo básico de los bucles, vamos a ver ejemplos de cómo usarlos.
Ejemplo 1: generar la tabla de multiplicar
DO $$
DECLARE
i INT;
j INT;
BEGIN
FOR i IN 1..5 LOOP
FOR j IN 1..5 LOOP
RAISE NOTICE '% x % = %', i, j, i * j;
END LOOP;
END LOOP;
END $$;
Ejemplo 2: iterar sobre los resultados de una consulta. Supón que tienes una tabla products con los campos id y price. Vamos a actualizar todos los precios, subiéndolos un 10%.
DO $$
DECLARE
prod RECORD;
BEGIN
FOR prod IN QUERY (SELECT id, price FROM products) LOOP
UPDATE products
SET price = prod.price * 1.1
WHERE id = prod.id;
END LOOP;
END $$;
Errores típicos y cómo evitarlos
Bucle infinito en LOOP o WHILE. Si te olvidas de poner una condición de salida (EXIT o una condición correcta en WHILE), el bucle nunca termina. Es como conducir un coche sin frenos.
Error al iterar sobre el resultado de una consulta. Si la estructura de los datos resultantes no es la que esperas, puedes encontrarte con un error en el bucle FOR IN QUERY.
Consultas poco óptimas dentro de bucles. Por ejemplo, hacer un UPDATE en cada iteración puede ralentizar mucho la ejecución. En estos casos, es mejor usar una sola consulta SQL en vez de un bucle.
GO TO FULL VERSION