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
-- ...
ENDPará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');| nombre | precio |
|---|---|
| Samsung Galaxy S24 | 899.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;| productos | minimo | maximo | promedio |
|---|---|---|---|
| 4 | 599.99 | 1299.99 | 849.74 |
Comparación de tipos
| Tipo | Dirección | Valor inicial | Uso típico |
|---|---|---|---|
| IN | Entrada | Valor pasado | Filtros, criterios de búsqueda |
| OUT | Salida | NULL | Devolver resultados calculados |
| INOUT | Ambos | Valor pasado | Transformar 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
