LOOP
LOOP ejecuta un bloque de sentencias repetidamente hasta que se usa LEAVE para salir del bucle. Es el bucle más básico de MySQL y requiere una condición de salida explícita para evitar un bucle infinito.
Sintaxis
[etiqueta:] LOOP
sentencias;
IF condicion THEN
LEAVE etiqueta;
END IF;
END LOOP [etiqueta];La etiqueta es necesaria para que LEAVE identifique de qué bucle salir.
Ejemplo básico
DELIMITER //
CREATE PROCEDURE contar_hasta(IN limite INT)
BEGIN
DECLARE contador INT DEFAULT 1;
DECLARE resultado VARCHAR(500) DEFAULT '';
bucle: LOOP
IF contador > limite THEN
LEAVE bucle;
END IF;
SET resultado = CONCAT(resultado, contador, ' ');
SET contador = contador + 1;
END LOOP bucle;
SELECT TRIM(resultado) AS numeros;
END //
DELIMITER ;CALL contar_hasta(5);| numeros |
|---|
| 1 2 3 4 5 |
Generar datos con LOOP
DELIMITER //
CREATE PROCEDURE generar_series(IN inicio INT, IN fin INT, IN paso INT)
BEGIN
DECLARE i INT;
DROP TEMPORARY TABLE IF EXISTS tmp_series;
CREATE TEMPORARY TABLE tmp_series (valor INT);
SET i = inicio;
insertar: LOOP
IF i > fin THEN
LEAVE insertar;
END IF;
INSERT INTO tmp_series VALUES (i);
SET i = i + paso;
END LOOP insertar;
SELECT * FROM tmp_series;
DROP TEMPORARY TABLE tmp_series;
END //
DELIMITER ;CALL generar_series(10, 50, 10);| valor |
|---|
| 10 |
| 20 |
| 30 |
| 40 |
| 50 |
LOOP con procesamiento de datos
DELIMITER //
CREATE PROCEDURE ajustar_precios(IN porcentaje DECIMAL(5,2))
BEGIN
DECLARE v_id INT;
DECLARE v_precio DECIMAL(10,2);
DECLARE v_nuevo DECIMAL(10,2);
DECLARE v_done INT DEFAULT FALSE;
DECLARE v_contador INT DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT id, precio FROM productos WHERE precio > 1000 AND activo = TRUE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;
OPEN cur;
leer: LOOP
FETCH cur INTO v_id, v_precio;
IF v_done THEN
LEAVE leer;
END IF;
SET v_nuevo = v_precio * (1 + porcentaje / 100);
-- En producción: UPDATE productos SET precio = v_nuevo WHERE id = v_id;
SET v_contador = v_contador + 1;
END LOOP leer;
CLOSE cur;
SELECT v_contador AS productos_afectados;
END //
DELIMITER ;CALL ajustar_precios(5.00);| productos_afectados |
|---|
| 4 |
Bucle infinito sin LEAVE
Sin LEAVE, el bucle se ejecuta indefinidamente. MySQL tiene un límite de tiempo de ejecución que eventualmente lo detendrá:
-- NUNCA hacer esto:
-- mi_loop: LOOP
-- SELECT 1; -- Bucle infinito
-- END LOOP mi_loop;Siempre incluye una condición de salida con LEAVE.
LOOP vs otros bucles
| Bucle | Condición | Evaluación | Mínimo de ejecuciones |
|---|---|---|---|
| LOOP | Explícita con LEAVE | Dentro del cuerpo | 0 o más |
| WHILE | En la cabecera | Antes de cada iteración | 0 |
| REPEAT | En el pie | Después de cada iteración | 1 |
Limpieza
DROP PROCEDURE IF EXISTS contar_hasta;
DROP PROCEDURE IF EXISTS generar_series;
DROP PROCEDURE IF EXISTS ajustar_precios;En el siguiente artículo veremos el bucle WHILE, que evalúa la condición antes de cada iteración.
Escrito por Eduardo Lázaro
