Los procedimientos y funciones almacenados no son solo contenedores cómodos para un grupo de consultas. También te permiten implementar una lógica bastante compleja con bifurcaciones y bucles.

En este artículo veremos las principales estructuras de control de flujo: las sentencias condicionales IF y CASE y el bucle WHILE.

La sentencia condicional IF

La sentencia IF permite ejecutar código según se cumpla o no una condición.

Sintaxis de IF

MySQL 8.4
IF condicion THEN
    acciones
[ELSEIF condicion THEN
    acciones] ...
[ELSE
    acciones]
END IF;
  • [ ]parte opcional
  • ...se puede repetir
condicion

Una expresión lógica, por ejemplo student_age < 18. Se ejecuta la primera rama cuya condición sea verdadera y las demás se omiten.

acciones

Una o varias sentencias SQL, cada una terminada en ;. Se ejecutan si se elige esta rama.

ELSEIF

Otra rama con su propia condición. Solo se comprueba si todas las condiciones anteriores son falsas. Puede haber varias ramas así.

Palabra claveOpcional
ELSE

La rama que se ejecuta si ninguna condición ha resultado verdadera.

Palabra claveOpcional
MySQL 8.4
IF condicion THEN
    acciones
[ELSIF condicion THEN
    acciones] ...
[ELSE
    acciones]
END IF;
  • [ ]parte opcional
  • ...se puede repetir
condicion

Una expresión lógica, por ejemplo student_age < 18. Se ejecuta la primera rama cuya condición sea verdadera y las demás se omiten.

acciones

Una o varias sentencias SQL, cada una terminada en ;. Se ejecutan si se elige esta rama.

ELSIF

Otra rama con su propia condición. Solo se comprueba si todas las condiciones anteriores son falsas. Puede haber varias ramas así.

Palabra claveOpcional
ELSE

La rama que se ejecuta si ninguna condición ha resultado verdadera.

Palabra claveOpcional

Ejemplo de uso de IF

Vamos a crear un procedimiento que determina la categoría de un estudiante según su edad:

MySQL 8.4
CREATE PROCEDURE categorize_student_by_age(
    IN student_id INT,
    OUT category VARCHAR(20)
)
BEGIN
    DECLARE student_age INT;

    -- Obtenemos la edad del estudiante
    SELECT TIMESTAMPDIFF(YEAR, birthday, CURDATE())
    INTO student_age
    FROM Student
    WHERE id = student_id;

    -- Determinamos la categoría según la edad
    IF student_age < 18 THEN
        SET category = 'Menor de edad';
    ELSEIF student_age BETWEEN 18 AND 25 THEN
        SET category = 'Joven';
    ELSE
        SET category = 'Adulto';
    END IF;
END;

-- Uso del procedimiento
CALL categorize_student_by_age(1, @category);
SELECT @category AS age_category;

Vamos a crear una función que determina la categoría de un estudiante según su edad:

MySQL 8.4
CREATE OR REPLACE FUNCTION categorize_student_by_age(student_id INT)
RETURNS VARCHAR(20)
LANGUAGE plpgsql
AS $$
DECLARE
    student_age INT;
    category VARCHAR(20);
BEGIN
    -- Obtenemos la edad del estudiante
    SELECT EXTRACT(YEAR FROM AGE(CURRENT_DATE, birthday))
    INTO student_age
    FROM Student
    WHERE id = student_id;

    -- Determinamos la categoría según la edad
    IF student_age < 18 THEN
        category := 'Menor de edad';
    ELSIF student_age BETWEEN 18 AND 25 THEN
        category := 'Joven';
    ELSE
        category := 'Adulto';
    END IF;

    RETURN category;
END;
$$;

-- Uso de la función
SELECT categorize_student_by_age(1) AS age_category;
age_category
Joven

La sentencia CASE

La sentencia CASE ofrece una forma más elegante de procesar varias condiciones.

Sintaxis de CASE

MySQL 8.4
CASE
    WHEN condicion THEN resultado
    [WHEN ...]
    [ELSE resultado_por_defecto]
END
  • [ ]parte opcional
  • ...se puede repetir
condicion

Una expresión lógica que se comprueba en su rama WHEN. Puede haber varias ramas: se ejecuta la primera cuya condición sea verdadera.

resultado

El valor que toma CASE si la condición de esta rama es verdadera.

resultado_por_defecto

El valor para el caso en que no se cumpla ninguna condición. Sin ELSE se devuelve NULL.

Opcional
MySQL 8.4
CASE
    WHEN condicion THEN resultado
    [WHEN ...]
    [ELSE resultado_por_defecto]
END
  • [ ]parte opcional
  • ...se puede repetir
condicion

Una expresión lógica que se comprueba en su rama WHEN. Puede haber varias ramas: se ejecuta la primera cuya condición sea verdadera.

resultado

El valor que toma CASE si la condición de esta rama es verdadera.

resultado_por_defecto

El valor para el caso en que no se cumpla ninguna condición. Sin ELSE se devuelve NULL.

Opcional

Ejemplo de uso de CASE

Vamos a crear el mismo procedimiento de clasificación de estudiantes, pero ahora con la sentencia CASE:

MySQL 8.4
CREATE PROCEDURE categorize_student_with_case(
    IN student_id INT,
    OUT category VARCHAR(20)
)
BEGIN
    DECLARE student_age INT;

    -- Obtenemos la edad del estudiante
    SELECT TIMESTAMPDIFF(YEAR, birthday, CURDATE())
    INTO student_age
    FROM Student
    WHERE id = student_id;

    -- Determinamos la categoría con CASE
    SET category = CASE
        WHEN student_age < 18 THEN 'Menor de edad'
        WHEN student_age BETWEEN 18 AND 25 THEN 'Joven'
        ELSE 'Adulto'
    END;
END;

-- Uso del procedimiento
CALL categorize_student_with_case(1, @category);
SELECT @category AS age_category;

Vamos a crear la misma función de clasificación de estudiantes, pero ahora con la sentencia CASE:

MySQL 8.4
CREATE OR REPLACE FUNCTION categorize_student_with_case(student_id INT)
RETURNS VARCHAR(20)
LANGUAGE plpgsql
AS $$
DECLARE
    student_age INT;
    category VARCHAR(20);
BEGIN
    -- Obtenemos la edad del estudiante
    SELECT EXTRACT(YEAR FROM AGE(CURRENT_DATE, birthday))
    INTO student_age
    FROM Student
    WHERE id = student_id;

    -- Determinamos la categoría con CASE
    category := CASE
        WHEN student_age < 18 THEN 'Menor de edad'
        WHEN student_age BETWEEN 18 AND 25 THEN 'Joven'
        ELSE 'Adulto'
    END;

    RETURN category;
END;
$$;

-- Uso de la función
SELECT categorize_student_with_case(1) AS age_category;
age_category
Joven

El bucle WHILE

El bucle WHILE permite ejecutar código repetidamente mientras se cumpla una condición determinada.

Sintaxis de WHILE

MySQL 8.4
WHILE condicion DO
    acciones
END WHILE;
condicion

Una expresión lógica que se comprueba antes de cada pasada del bucle. Mientras sea verdadera, las acciones se repiten.

acciones

Las sentencias SQL del cuerpo del bucle. Entre ellas debe haber algo que, tarde o temprano, haga falsa la condición; si no, el bucle no terminará nunca.

MySQL 8.4
WHILE condicion LOOP
    acciones
END LOOP;
condicion

Una expresión lógica que se comprueba antes de cada pasada del bucle. Mientras sea verdadera, las acciones se repiten.

acciones

Las sentencias SQL del cuerpo del bucle. Entre ellas debe haber algo que, tarde o temprano, haga falsa la condición; si no, el bucle no terminará nunca.

Ejemplo de uso de WHILE

Veamos un ejemplo de procedimiento almacenado que crea varias asignaturas de prueba:

MySQL 8.4
CREATE PROCEDURE create_test_subjects(IN count_subjects INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE subject_id INT DEFAULT 20;

    WHILE i <= count_subjects DO
        INSERT INTO Subject (id, name)
        VALUES
        (
            subject_id + i,
            CONCAT('Test Subject ', i)
        );

        SET i = i + 1;
    END WHILE;
END;

-- Creamos 3 asignaturas de prueba
CALL create_test_subjects(3);

-- Comprobamos el resultado
SELECT * FROM Subject WHERE name LIKE 'Test Subject%';
MySQL 8.4
CREATE OR REPLACE PROCEDURE create_test_subjects(count_subjects INT)
LANGUAGE plpgsql
AS $$
DECLARE
    i INT := 1;
    subject_id INT := 20;
BEGIN
    WHILE i <= count_subjects LOOP
        INSERT INTO Subject (id, name)
        VALUES
        (
            subject_id + i,
            'Test Subject ' || i
        );

        i := i + 1;
    END LOOP;

    RAISE NOTICE 'Se han creado % asignaturas de prueba', count_subjects;
END;
$$;

-- Creamos 3 asignaturas de prueba
CALL create_test_subjects(3);

-- Comprobamos el resultado
SELECT * FROM Subject WHERE name LIKE 'Test Subject%';
idname
21Test Subject 1
22Test Subject 2
23Test Subject 3

¡Las estructuras de control de flujo convierten los procedimientos y funciones almacenados en una herramienta potente para implementar lógica de negocio compleja directamente en la base de datos! 🚀