WHILE
El bucle WHILE ejecuta un bloque de sentencias repetidamente mientras una condición sea verdadera. La condición se evalúa antes de cada iteración, por lo que si es falsa desde el inicio, el cuerpo nunca se ejecuta.
Sintaxis
[etiqueta:] WHILE condicion DO
sentencias;
END WHILE [etiqueta];Ejemplo básico
DELIMITER //
CREATE PROCEDURE cuenta_regresiva(IN inicio INT)
BEGIN
DECLARE resultado VARCHAR(500) DEFAULT '';
WHILE inicio > 0 DO
SET resultado = CONCAT(resultado, inicio, ' ');
SET inicio = inicio - 1;
END WHILE;
SELECT TRIM(resultado) AS cuenta;
END //
DELIMITER ;CALL cuenta_regresiva(5);| cuenta |
|---|
| 5 4 3 2 1 |
Calcular factorial
DELIMITER //
CREATE PROCEDURE factorial(IN n INT, OUT resultado BIGINT)
BEGIN
SET resultado = 1;
WHILE n > 1 DO
SET resultado = resultado * n;
SET n = n - 1;
END WHILE;
END //
DELIMITER ;CALL factorial(5, @fact);
SELECT @fact AS factorial_5;| factorial_5 |
|---|
| 120 |
CALL factorial(10, @fact);
SELECT @fact AS factorial_10;| factorial_10 |
|---|
| 3628800 |
WHILE con datos
DELIMITER //
CREATE PROCEDURE top_productos_por_valor(IN limite INT)
BEGIN
DECLARE v_contador INT DEFAULT 0;
DROP TEMPORARY TABLE IF EXISTS tmp_ranking;
CREATE TEMPORARY TABLE tmp_ranking (
posicion INT,
nombre VARCHAR(100),
valor_stock DECIMAL(12,2)
);
INSERT INTO tmp_ranking
SELECT NULL, nombre, precio * stock AS valor
FROM productos
WHERE activo = TRUE
ORDER BY valor DESC;
-- Asignar posiciones manualmente
SET @pos = 0;
UPDATE tmp_ranking SET posicion = (@pos := @pos + 1);
SELECT posicion, nombre, valor_stock
FROM tmp_ranking
WHERE posicion <= limite;
DROP TEMPORARY TABLE tmp_ranking;
END //
DELIMITER ;CALL top_productos_por_valor(5);WHILE con acumulador
DELIMITER //
CREATE PROCEDURE sumar_precios_hasta(IN limite DECIMAL(10,2))
BEGIN
DECLARE v_nombre VARCHAR(100);
DECLARE v_precio DECIMAL(10,2);
DECLARE v_suma DECIMAL(10,2) DEFAULT 0;
DECLARE v_contador INT DEFAULT 0;
DECLARE v_done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR
SELECT nombre, precio FROM productos
WHERE activo = TRUE ORDER BY precio;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;
OPEN cur;
FETCH cur INTO v_nombre, v_precio;
WHILE NOT v_done AND (v_suma + v_precio) <= limite DO
SET v_suma = v_suma + v_precio;
SET v_contador = v_contador + 1;
FETCH cur INTO v_nombre, v_precio;
END WHILE;
CLOSE cur;
SELECT v_contador AS productos_incluidos,
v_suma AS total_acumulado,
limite AS presupuesto;
END //
DELIMITER ;CALL sumar_precios_hasta(500.00);| productos_incluidos | total_acumulado | presupuesto |
|---|---|---|
| 7 | 447.89 | 500.00 |
Condición falsa desde el inicio
DELIMITER //
CREATE PROCEDURE ejemplo_while_vacio()
BEGIN
DECLARE i INT DEFAULT 10;
DECLARE ejecuto VARCHAR(5) DEFAULT 'No';
-- La condición es falsa desde el inicio
WHILE i < 5 DO
SET ejecuto = 'Sí';
SET i = i + 1;
END WHILE;
SELECT ejecuto AS se_ejecuto, i AS valor_i;
END //
DELIMITER ;CALL ejemplo_while_vacio();| se_ejecuto | valor_i |
|---|---|
| No | 10 |
El cuerpo del WHILE no se ejecuta ni una vez porque 10 < 5 es falso.
Limpieza
DROP PROCEDURE IF EXISTS cuenta_regresiva;
DROP PROCEDURE IF EXISTS factorial;
DROP PROCEDURE IF EXISTS top_productos_por_valor;
DROP PROCEDURE IF EXISTS sumar_precios_hasta;
DROP PROCEDURE IF EXISTS ejemplo_while_vacio;En el siguiente artículo veremos el bucle REPEAT, que garantiza al menos una ejecución del cuerpo.
Escrito por Eduardo Lázaro
