LEAVE

LEAVE sale de un bucle o de un bloque BEGIN...END etiquetado. Es el equivalente a break en lenguajes como JavaScript, Java o C. Se usa con LOOP, WHILE, REPEAT y bloques BEGIN...END.

Sintaxis

LEAVE etiqueta;

LEAVE en un LOOP

DELIMITER //
 
CREATE PROCEDURE buscar_primer_caro(IN umbral DECIMAL(10,2))
BEGIN
    DECLARE v_id INT;
    DECLARE v_nombre VARCHAR(100);
    DECLARE v_precio DECIMAL(10,2);
    DECLARE v_done INT DEFAULT FALSE;
 
    DECLARE cur CURSOR FOR
        SELECT id, nombre, precio FROM productos ORDER BY id;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;
 
    OPEN cur;
 
    buscar: LOOP
        FETCH cur INTO v_id, v_nombre, v_precio;
 
        IF v_done THEN
            LEAVE buscar;
        END IF;
 
        -- Salir cuando encontramos el primer producto caro
        IF v_precio >= umbral THEN
            SELECT v_id AS id, v_nombre AS nombre, v_precio AS precio,
                   'Primer producto encontrado' AS mensaje;
            LEAVE buscar;
        END IF;
    END LOOP buscar;
 
    CLOSE cur;
END //
 
DELIMITER ;
CALL buscar_primer_caro(1500);
idnombrepreciomensaje
6Lenovo ThinkPad X11549.00Primer producto encontrado

LEAVE en un WHILE

DELIMITER //
 
CREATE PROCEDURE sumar_hasta_limite(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 DESC;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = TRUE;
 
    OPEN cur;
 
    acumular: WHILE NOT v_done DO
        FETCH cur INTO v_nombre, v_precio;
 
        IF v_done THEN
            LEAVE acumular;
        END IF;
 
        IF v_suma + v_precio > limite THEN
            LEAVE acumular;
        END IF;
 
        SET v_suma = v_suma + v_precio;
        SET v_contador = v_contador + 1;
    END WHILE acumular;
 
    CLOSE cur;
 
    SELECT v_contador AS productos,
           v_suma AS total,
           limite AS presupuesto,
           limite - v_suma AS restante;
END //
 
DELIMITER ;
CALL sumar_hasta_limite(5000);
productostotalpresupuestorestante
44947.985000.0052.02

LEAVE en un bloque BEGIN...END

LEAVE puede salir de un bloque etiquetado, no solo de bucles. Esto es útil para implementar salidas tempranas:

DELIMITER //
 
CREATE PROCEDURE verificar_y_procesar(IN prod_id INT)
BEGIN
    DECLARE v_existe INT;
    DECLARE v_activo BOOLEAN;
    DECLARE v_stock INT;
    DECLARE v_nombre VARCHAR(100);
 
    principal: BEGIN
        -- Verificar que existe
        SELECT COUNT(*) INTO v_existe FROM productos WHERE id = prod_id;
        IF v_existe = 0 THEN
            SELECT 'Producto no encontrado' AS error;
            LEAVE principal;
        END IF;
 
        -- Verificar que está activo
        SELECT activo, stock, nombre INTO v_activo, v_stock, v_nombre
        FROM productos WHERE id = prod_id;
 
        IF v_activo = FALSE THEN
            SELECT 'Producto no activo' AS error;
            LEAVE principal;
        END IF;
 
        -- Verificar stock
        IF v_stock = 0 THEN
            SELECT 'Producto sin stock' AS error;
            LEAVE principal;
        END IF;
 
        -- Si llegamos aquí, todo está bien
        SELECT v_nombre AS producto, v_stock AS stock, 'OK' AS estado;
    END principal;
END //
 
DELIMITER ;
CALL verificar_y_procesar(1);
productostockestado
iPhone 15 Pro45OK
CALL verificar_y_procesar(999);
error
Producto no encontrado

LEAVE con bucles anidados

DELIMITER //
 
CREATE PROCEDURE buscar_en_matriz()
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE j INT;
    DECLARE encontrado BOOLEAN DEFAULT FALSE;
 
    exterior: LOOP
        IF i > 10 THEN
            LEAVE exterior;
        END IF;
 
        SET j = 1;
 
        interior: LOOP
            IF j > 10 THEN
                LEAVE interior;
            END IF;
 
            IF i * j = 42 THEN
                SELECT i AS fila, j AS columna,
                       CONCAT(i, ' x ', j, ' = 42') AS resultado;
                SET encontrado = TRUE;
                LEAVE exterior;  -- Sale del bucle exterior
            END IF;
 
            SET j = j + 1;
        END LOOP interior;
 
        SET i = i + 1;
    END LOOP exterior;
 
    IF NOT encontrado THEN
        SELECT 'No encontrado' AS resultado;
    END IF;
END //
 
DELIMITER ;
CALL buscar_en_matriz();
filacolumnaresultado
676 x 7 = 42

Limpieza

DROP PROCEDURE IF EXISTS buscar_primer_caro;
DROP PROCEDURE IF EXISTS sumar_hasta_limite;
DROP PROCEDURE IF EXISTS verificar_y_procesar;
DROP PROCEDURE IF EXISTS buscar_en_matriz;

En el siguiente artículo veremos ITERATE, que salta a la siguiente iteración de un bucle.

Escrito por Eduardo Lázaro