Parámetros

Los procedimientos almacenados pueden recibir y devolver datos a través de parámetros. MySQL soporta tres tipos: IN para entrada, OUT para salida e INOUT para ambos.

Sintaxis

CREATE PROCEDURE nombre(
    IN parametro_entrada tipo,
    OUT parametro_salida tipo,
    INOUT parametro_bidireccional tipo
)
BEGIN
    -- ...
END

Parámetro IN

IN es el tipo por defecto. El procedimiento recibe una copia del valor; los cambios dentro del procedimiento no afectan al exterior.

DELIMITER //
 
CREATE PROCEDURE buscar_productos(IN texto VARCHAR(100))
BEGIN
    SELECT nombre, precio
    FROM productos
    WHERE nombre LIKE CONCAT('%', texto, '%')
    ORDER BY precio;
END //
 
DELIMITER ;
CALL buscar_productos('Samsung');
nombreprecio
Samsung Galaxy S24899.99
Samsung TV QLED 55"749.00
-- IN es implícito, estas dos formas son equivalentes:
-- IN texto VARCHAR(100)
-- texto VARCHAR(100)

Parámetro OUT

OUT permite al procedimiento devolver un valor al llamador. El parámetro comienza como NULL dentro del procedimiento.

DELIMITER //
 
CREATE PROCEDURE contar_por_categoria(
    IN cat_id INT,
    OUT total INT
)
BEGIN
    SELECT COUNT(*) INTO total
    FROM productos
    WHERE categoria_id = cat_id AND activo = TRUE;
END //
 
DELIMITER ;
CALL contar_por_categoria(6, @total);
SELECT @total AS total_electronica;
total_electronica
4

Los parámetros OUT se reciben usando variables de sesión con el prefijo @.

Parámetro INOUT

INOUT combina IN y OUT. El procedimiento recibe el valor y puede modificarlo.

DELIMITER //
 
CREATE PROCEDURE aplicar_descuento(INOUT precio DECIMAL(10,2), IN porcentaje INT)
BEGIN
    SET precio = precio - (precio * porcentaje / 100);
END //
 
DELIMITER ;
SET @mi_precio = 1299.99;
CALL aplicar_descuento(@mi_precio, 15);
SELECT @mi_precio AS precio_con_descuento;
precio_con_descuento
1104.99

Múltiples parámetros OUT

DELIMITER //
 
CREATE PROCEDURE estadisticas_categoria(
    IN cat_id INT,
    OUT total_prod INT,
    OUT precio_min DECIMAL(10,2),
    OUT precio_max DECIMAL(10,2),
    OUT precio_medio DECIMAL(10,2)
)
BEGIN
    SELECT COUNT(*), MIN(precio), MAX(precio), AVG(precio)
    INTO total_prod, precio_min, precio_max, precio_medio
    FROM productos
    WHERE categoria_id = cat_id AND activo = TRUE;
END //
 
DELIMITER ;
CALL estadisticas_categoria(6, @total, @min, @max, @avg);
SELECT @total AS productos, @min AS minimo, @max AS maximo, @avg AS promedio;
productosminimomaximopromedio
4599.991299.99849.74

Comparación de tipos

TipoDirecciónValor inicialUso típico
INEntradaValor pasadoFiltros, criterios de búsqueda
OUTSalidaNULLDevolver resultados calculados
INOUTAmbosValor pasadoTransformar un valor

Ejemplo completo

DELIMITER //
 
CREATE PROCEDURE procesar_pedido(
    IN cliente INT,
    IN producto INT,
    IN cantidad INT,
    OUT pedido_id INT,
    OUT mensaje VARCHAR(200)
)
BEGIN
    DECLARE stock_actual INT;
    DECLARE precio_prod DECIMAL(10,2);
 
    -- Verificar stock
    SELECT stock, precio INTO stock_actual, precio_prod
    FROM productos WHERE id = producto;
 
    IF stock_actual >= cantidad THEN
        -- Crear pedido
        INSERT INTO pedidos (cliente_id, fecha, total, estado)
        VALUES (cliente, CURDATE(), precio_prod * cantidad, 'pendiente');
 
        SET pedido_id = LAST_INSERT_ID();
 
        -- Añadir detalle
        INSERT INTO detalle_pedidos (pedido_id, producto_id, cantidad, precio_unitario)
        VALUES (pedido_id, producto, cantidad, precio_prod);
 
        -- Actualizar stock
        UPDATE productos SET stock = stock - cantidad WHERE id = producto;
 
        SET mensaje = CONCAT('Pedido #', pedido_id, ' creado correctamente');
    ELSE
        SET pedido_id = 0;
        SET mensaje = CONCAT('Stock insuficiente. Disponible: ', stock_actual);
    END IF;
END //
 
DELIMITER ;

Limpieza

DROP PROCEDURE IF EXISTS buscar_productos;
DROP PROCEDURE IF EXISTS contar_por_categoria;
DROP PROCEDURE IF EXISTS aplicar_descuento;
DROP PROCEDURE IF EXISTS estadisticas_categoria;
DROP PROCEDURE IF EXISTS procesar_pedido;

En el siguiente artículo veremos las variables dentro de procedimientos almacenados.

Escrito por Eduardo Lázaro