Un procedimiento almacenado (Stored Procedure
) en MySQL es un bloque de código SQL que se guarda en la base de datos y se puede ejecutar múltiples veces sin necesidad de reescribirlo.
✅ Reutilización: Se pueden llamar múltiples veces con diferentes parámetros.
✅ Mejor rendimiento: Se ejecutan en el servidor sin enviar múltiples consultas desde el cliente.
✅ Seguridad: Se pueden controlar los permisos y restringir acceso directo a los datos.
✅ Modularidad: Facilitan la organización del código SQL.
La sintaxis básica es:
DELIMITER $$
CREATE PROCEDURE nombre_procedimiento()
BEGIN
-- Instrucciones SQL
END $$
DELIMITER ;
🔹 DELIMITER $$
→ Se cambia el delimitador para evitar que MySQL termine la consulta antes de tiempo.
🔹 CREATE PROCEDURE nombre_procedimiento()
→ Define el procedimiento.
🔹 BEGIN ... END
→ Indica el bloque de instrucciones SQL.
🔹 DELIMITER ;
→ Se vuelve a establecer el delimitador estándar.
DELIMITER $$
CREATE PROCEDURE ObtenerClientes()
BEGIN
SELECT * FROM clientes;
END $$
DELIMITER ;
🔹 Ejecutar el procedimiento
CALL ObtenerClientes();
✅ Muestra todos los clientes de la tabla clientes
.
Los procedimientos pueden recibir parámetros de entrada (IN
), salida (OUT
), o ambos (INOUT
).
IN
)DELIMITER $$
CREATE PROCEDURE ObtenerClientePorID(IN id_cliente INT)
BEGIN
SELECT * FROM clientes WHERE clientes.id_cliente = id_cliente;
END $$
DELIMITER ;
🔹 Ejecutar el procedimiento
CALL ObtenerClientePorID(2);
✅ Filtra clientes por id_cliente
.
OUT
)DELIMITER $$
CREATE PROCEDURE ContarClientes(OUT total INT)
BEGIN
SELECT COUNT(*) INTO total FROM clientes;
END $$
DELIMITER ;
🔹 Ejecutar el procedimiento con una variable de salida
CALL ContarClientes(@total);
SELECT @total;
✅ Devuelve el número total de clientes.
INOUT
)DELIMITER $$
CREATE PROCEDURE DuplicarNumero(INOUT numero INT)
BEGIN
SET numero = numero * 2;
END $$
DELIMITER ;
🔹 Ejecutar el procedimiento
SET @valor = 5;
CALL DuplicarNumero(@valor);
SELECT @valor;
✅ Multiplica @valor
por 2 y lo devuelve.
IF
, CASE
, LOOP
)Los procedimientos pueden incluir estructuras de control como condicionales y bucles.
IF
para Validar SaldoDELIMITER $$
CREATE PROCEDURE TransferirSaldo(IN cuenta_origen INT, IN cuenta_destino INT, IN monto DECIMAL(10,2))
BEGIN
DECLARE saldo_actual DECIMAL(10,2);
-- Obtener saldo de la cuenta origen
SELECT saldo INTO saldo_actual FROM cuentas WHERE id_cuenta = cuenta_origen;
-- Validar saldo suficiente
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 ;
🔹 Ejecutar el procedimiento
CALL TransferirSaldo(1, 2, 500);
✅ Solo transfiere el dinero si la cuenta tiene saldo suficiente.
WHILE
, LOOP
, REPEAT
)WHILE
para Calcular FactorialDELIMITER $$
CREATE PROCEDURE CalcularFactorial(IN num INT, OUT resultado INT)
BEGIN
DECLARE i INT DEFAULT 1;
SET resultado = 1;
WHILE i <= num DO
SET resultado = resultado * i;
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
🔹 Ejecutar el procedimiento
CALL CalcularFactorial(5, @resultado);
SELECT @resultado; -- Resultado: 120
✅ Calcula el factorial de un número usando WHILE
.
DECLARE HANDLER
Se pueden capturar errores dentro de los procedimientos usando DECLARE HANDLER
.
🔹 Ejemplo: Manejo de errores en una transferencia bancaria
DELIMITER $$
CREATE PROCEDURE TransferenciaBancaria(
IN cuenta_origen INT,
IN cuenta_destino INT,
IN monto DECIMAL(10,2)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error en la transacción';
END;
START TRANSACTION;
UPDATE cuentas SET saldo = saldo - monto WHERE id_cuenta = cuenta_origen;
UPDATE cuentas SET saldo = saldo + monto WHERE id_cuenta = cuenta_destino;
COMMIT;
END $$
DELIMITER ;
🔹 Si ocurre un error, la transacción se revierte automáticamente.
🔹 Ver los procedimientos almacenados en una base de datos
SHOW PROCEDURE STATUS WHERE Db = 'mi_base_de_datos';
🔹 Eliminar un procedimiento
DROP PROCEDURE IF EXISTS ObtenerClientes;
🔹 Modificar un procedimiento (se debe eliminar y volver a crear)
DROP PROCEDURE IF EXISTS ObtenerClientes;
DELIMITER $$
CREATE PROCEDURE ObtenerClientes()
BEGIN
SELECT id_cliente, nombre FROM clientes; -- Ahora solo devuelve ID y nombre
END $$
DELIMITER ;
Característica | Procedimiento (PROCEDURE ) |
Función (FUNCTION ) |
---|---|---|
Devuelve valores | ✅ Sí (OUT , INOUT ) |
✅ Sí (RETURN ) |
Se usa en consultas (SELECT ) |
❌ No | ✅ Sí |
Puede modificar datos (INSERT , UPDATE , etc.) |
✅ Sí | ❌ No |
Puede devolver múltiples valores | ✅ Sí (OUT ) |
❌ No |
✅ Usa procedimientos almacenados para tareas repetitivas y automatización.
✅ Evita procedimientos largos; divídelos en varios más pequeños si es necesario.
✅ Usa manejo de errores (DECLARE HANDLER
) para mayor seguridad.
✅ Prueba siempre el procedimiento antes de usarlo en producción.
✅ Usa transacciones (START TRANSACTION
, COMMIT
, ROLLBACK
) para evitar errores críticos en la base de datos.