En MySQL, el control de flujo permite tomar decisiones y repetir operaciones dentro de procedimientos almacenados, funciones, y triggers.
Las principales estructuras de control de flujo son:
IF
, CASE
) → Para tomar decisiones.LOOP
, WHILE
, REPEAT
) → Para ejecutar código repetidamente.LEAVE
, ITERATE
) → Para gestionar el flujo de ejecución.IF ... THEN ... ELSE
Se usa para evaluar una condición y ejecutar diferentes bloques de código.
IF condición THEN
-- Código a ejecutar si la condición es verdadera
ELSE
-- Código a ejecutar si la condición es falsa
END IF;
CREATE DEFINER=`3eva`@`%` FUNCTION `aplica_porcentaje`(
`pBase` DECIMAL(10,2),
`pPorcentaje` DECIMAL(6,2),
`pTipo` CHAR(1)
)
RETURNS decimal(10,2)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE res DECIMAL(10,2);
if (lower(pTipo)="i") then
SET res := pBase*(1+pPorcentaje/100);
ELSE
if (lower(pTipo)="d") then
SET res := pBase*(1-pPorcentaje/100);
else
SET res := -1;
END if;
END if;
RETURN res;
END
SET @a:=(select aplica_porcentaje(100,21,"i"));
SET @b:=(select aplica_porcentaje(@a,50,"d"));
SELECT
@b,
aplica_porcentaje(aplica_porcentaje(100,21,"i"),50,"d"), aplica_porcentaje(100,21,"a")
;
🔹 Ejemplo: Validar saldo antes de realizar una transferencia
DELIMITER $$
CREATE PROCEDURE TransferirDinero(IN cuenta_origen INT, IN cuenta_destino INT, IN monto DECIMAL(10,2))
BEGIN
DECLARE saldo_actual DECIMAL(10,2);
-- Obtener el saldo de la cuenta de origen
SELECT saldo INTO saldo_actual FROM cuentas WHERE id_cuenta = cuenta_origen;
-- Verificar si hay suficiente saldo
IF saldo_actual >= monto THEN
UPDATE cuentas SET saldo = saldo - monto WHERE id_cuenta = cuenta_origen;
UPDATE cuentas SET saldo = saldo + monto WHERE id_cuenta = cuenta_destino;
ELSE
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Saldo insuficiente';
END IF;
END $$
DELIMITER ;
✅ Si hay saldo suficiente, se realiza la transferencia; de lo contrario, se genera un error.
CASE
(Similar a switch
en otros lenguajes)Se usa para evaluar múltiples condiciones sin escribir muchos IF
.
CASE valor
WHEN opción1 THEN resultado1
WHEN opción2 THEN resultado2
ELSE resultado_default
END;
🔹 **Ejemplo:
CREATE DEFINER=`3eva`@`%` FUNCTION `aplica_porcentaje2`(
`pBase` DECIMAL(10,2),
`pPorcentaje` DECIMAL(6,2),
`pTipo` CHAR(1)
)
RETURNS decimal(10,2)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE res DECIMAL(10,2);
case lower(pTipo)
WHEN "i" THEN
SET res := pBase*(1+pPorcentaje/100);
WHEN "d" THEN
SET res := pBase*(1-pPorcentaje/100);
ELSE
SET res := -1;
END case;
RETURN res;
END
🔹 Ejemplo: Determinar la categoría de un producto según su precio
DELIMITER $$
CREATE FUNCTION CategoriaProducto(precio DECIMAL(10,2)) RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
DECLARE categoria VARCHAR(20);
SET categoria = CASE
WHEN precio < 50 THEN 'Económico'
WHEN precio BETWEEN 50 AND 200 THEN 'Estándar'
ELSE 'Premium'
END;
RETURN categoria;
END $$
DELIMITER ;
📌 Uso en una consulta
SELECT nombre, CategoriaProducto(precio) AS categoria FROM productos;
✅ Se clasifica cada producto según su precio.
Los bucles permiten repetir instrucciones hasta que se cumpla una condición.
LOOP
(Iteración infinita controlada)LOOP
-- Código dentro del bucle
IF condición_de_salida THEN
LEAVE nombre_bucle;
END IF;
END LOOP;
CREATE DEFINER=`eva3`@`%` FUNCTION `factorial3`(
`pNum` INT
)
RETURNS bigint
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE res BIGINT DEFAULT 1;
if pNum > 1 then
bucle: loop
SET res := res * pNum;
SET pNum := pNum-1;
if pNum = 1 then
leave bucle;
END if;
END loop;
END if;
RETURN res;
END
🔹 Ejemplo: Bucle para sumar los primeros 10 números
DELIMITER $$
CREATE PROCEDURE SumarNumeros()
BEGIN
DECLARE suma INT DEFAULT 0;
DECLARE contador INT DEFAULT 1;
nombre_bucle: LOOP
SET suma = suma + contador;
SET contador = contador + 1;
IF contador > 10 THEN
LEAVE nombre_bucle;
END IF;
END LOOP;
SELECT suma AS resultado;
END $$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo_bucle_loop$$
CREATE PROCEDURE ejemplo_bucle_loop(IN tope INT, OUT suma INT)
BEGIN
DECLARE contador INT;
SET contador = 1;
SET suma = 0;
bucle: LOOP
IF contador > tope THEN
LEAVE bucle;
END IF;
SET suma = suma + contador;
SET contador = contador + 1;
END LOOP;
END
$$
DELIMITER ;
CALL ejemplo_bucle_loop(10, @resultado);
SELECT @resultado;
📌 Llamada
CALL SumarNumeros();
✅ El procedimiento suma los números del 1 al 10 y muestra el resultado.
WHILE
(Iteración con condición)WHILE condición DO
-- Código dentro del bucle
END WHILE;
CREATE DEFINER=`3eva`@`%` FUNCTION `factorial`(
`pNum` INT
)
RETURNS bigint
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE i INT default pNum-1;
DECLARE res INT;
SET res:= pNum;
while i > 1 DO
SET res := res * i;
SET i := i - 1;
END while;
RETURN res;
END
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo_bucle_loop$$
CREATE PROCEDURE ejemplo_bucle_loop(IN tope INT, OUT suma INT)
BEGIN
DECLARE contador INT;
SET contador = 1;
SET suma = 0;
bucle: LOOP
IF contador > tope THEN
LEAVE bucle;
END IF;
SET suma = suma + contador;
SET contador = contador + 1;
END LOOP;
END
$$
DELIMITER ;
CALL ejemplo_bucle_loop(10, @resultado);
SELECT @resultado;
🔹 Ejemplo: Contar cuántos clientes tienen más de 5 pedidos
DELIMITER $$
CREATE PROCEDURE ContarClientesFrecuentes()
BEGIN
DECLARE contador INT DEFAULT 0;
DECLARE id_cliente INT;
DECLARE cursor_clientes CURSOR FOR
SELECT id_cliente FROM clientes;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET id_cliente = NULL;
OPEN cursor_clientes;
leer_clientes: LOOP
FETCH cursor_clientes INTO id_cliente;
IF id_cliente IS NULL THEN
LEAVE leer_clientes;
END IF;
IF (SELECT COUNT(*) FROM pedidos WHERE pedidos.id_cliente = id_cliente) > 5 THEN
SET contador = contador + 1;
END IF;
END LOOP;
CLOSE cursor_clientes;
SELECT contador AS clientes_frecuentes;
END $$
DELIMITER ;
📌 Llamada
CALL ContarClientesFrecuentes();
✅ Cuenta cuántos clientes han realizado más de 5 pedidos.
REPEAT
(Ejecuta al menos una vez)REPEAT
-- Código dentro del bucle
UNTIL condición_fin END REPEAT;
CREATE DEFINER=`eva3`@`%` FUNCTION `factorial2`(
`pNum` INT
)
RETURNS bigint
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE i INT DEFAULT pNum-1;
DECLARE total BIGINT;
SET total:= pNum;
if pNum > 1 then
repeat
SET total:= total * i;
SET i:= i-1;
until i<=1 END repeat;
else
SET total:= pNum;
END if;
RETURN total;
END
🔹 Ejemplo: Restar números hasta llegar a cero
DELIMITER $$
CREATE PROCEDURE ContadorRegresivo(INOUT numero INT)
BEGIN
REPEAT
SET numero = numero - 1;
UNTIL numero = 0 END REPEAT;
END $$
DELIMITER ;
📌 Llamada
SET @valor = 5;
CALL ContadorRegresivo(@valor);
SELECT @valor;
✅ El número se reduce hasta llegar a cero.
LEAVE
(Salir de un bucle)Se usa para salir de un LOOP
, WHILE
o REPEAT
.
LEAVE nombre_bucle;
ITERATE
(Saltar a la siguiente iteración)Se usa dentro de LOOP
para saltar una iteración sin salir del bucle.
ITERATE nombre_bucle;
🔹 Ejemplo: Saltar los números pares en un bucle
DELIMITER $$
CREATE PROCEDURE MostrarImpares()
BEGIN
DECLARE num INT DEFAULT 0;
impares: LOOP
SET num = num + 1;
IF num % 2 = 0 THEN
ITERATE impares; -- Salta la iteración si el número es par
END IF;
SELECT num;
IF num >= 10 THEN
LEAVE impares;
END IF;
END LOOP;
END $$
DELIMITER ;
✅ Solo muestra números impares del 1 al 10.
✅ Usa IF
y CASE
para controlar el flujo según condiciones.
✅ Usa LOOP
, WHILE
y REPEAT
para realizar operaciones repetitivas.
✅ Usa LEAVE
para salir de un bucle y ITERATE
para saltar iteraciones.
✅ Mantén los bucles eficientes y evita iteraciones innecesarias.
✅ Prueba siempre el código en un entorno seguro antes de ejecutarlo en producción.