En PL/pgSQL, las stored procedures (procedimientos almacenados) son bloques de código reutilizables que ejecutan una serie de operaciones en la base de datos. A diferencia de las funciones, los procedimientos no devuelven un valor, sino que se usan para realizar tareas como insertar, actualizar, eliminar registros o ejecutar operaciones administrativas.
Características principales de los procedimientos almacenados en PL/pgSQL
- No devuelven valores: A diferencia de las funciones, un procedimiento no utiliza
RETURN para devolver datos.
- Ejecutados con
CALL: Para invocarlos se usa la sentencia CALL.
- Manejo de transacciones: Los procedimientos pueden realizar operaciones de control de transacciones como
COMMIT y ROLLBACK.
- Reutilización: Reducen la repetición de código en consultas y operaciones frecuentes.
- Optimización: Mejoran el rendimiento al ejecutar la lógica cerca de los datos.
Sintaxis básica
La sintaxis para crear un procedimiento almacenado es:
CREATE PROCEDURE nombre_procedimiento(parámetros)
LANGUAGE plpgsql
AS $$
BEGIN
-- Código PL/pgSQL aquí
END;
$$;
Para ejecutar el procedimiento:
CALL nombre_procedimiento(parámetros);
Ejemplo 1: Procedimiento básico
Este procedimiento inserta un registro en una tabla llamada usuarios:
CREATE PROCEDURE insertar_usuario(nombre TEXT, edad INT)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO usuarios (nombre, edad) VALUES (nombre, edad);
END;
$$;
Uso:
CALL insertar_usuario('Mario', 30);
Ejemplo 2: Procedimiento con manejo de transacciones
En este ejemplo, el procedimiento registra un pedido y actualiza el inventario. Si algo falla, se revierte la transacción.
CREATE PROCEDURE registrar_pedido(id_producto INT, cantidad INT, cliente TEXT)
LANGUAGE plpgsql
AS $$
BEGIN
-- Registrar el pedido
INSERT INTO pedidos (producto_id, cantidad, cliente, fecha)
VALUES (id_producto, cantidad, cliente, NOW());
-- Actualizar el inventario
UPDATE inventario
SET stock = stock - cantidad
WHERE producto_id = id_producto;
-- Validar stock negativo
IF (SELECT stock FROM inventario WHERE producto_id = id_producto) < 0 THEN
RAISE EXCEPTION 'Stock insuficiente para el producto %', id_producto;
END IF;
END;
$$;
Uso:
CALL registrar_pedido(1, 5, 'Cliente1');
Ejemplo 3: Procedimiento con bucles y lógica
Un procedimiento que actualiza precios de productos por categoría con un incremento porcentual:
CREATE PROCEDURE actualizar_precios(categoria_id INT, incremento FLOAT)
LANGUAGE plpgsql
AS $$
BEGIN
FOR producto IN
SELECT id, precio
FROM productos
WHERE categoria_id = categoria_id
LOOP
UPDATE productos
SET precio = precio * (1 + incremento)
WHERE id = producto.id;
END LOOP;
END;
$$;
Uso:
CALL actualizar_precios(2, 0.10); -- Incrementa precios un 10% para categoría 2
Manejo de errores en procedimientos
Puedes capturar errores con bloques EXCEPTION para manejar situaciones inesperadas.
Ejemplo:
CREATE PROCEDURE ejemplo_error()
LANGUAGE plpgsql
AS $$
BEGIN
-- Intentar insertar un registro
INSERT INTO tabla_no_existente (columna) VALUES (1);
EXCEPTION
WHEN undefined_table THEN
RAISE NOTICE 'La tabla no existe. Operación cancelada.';
END;
$$;
Uso:
CALL ejemplo_error();
Comparación: Stored Procedures vs. Functions
CaracterísticaStored ProcedureFunctionRetorno de valoresNoSí (valor único o conjunto de datos)Uso de CALL o SELECTCALLSELECT o dentro de consultas SQLControl de transaccionesSí (COMMIT, ROLLBACK)No (depende del contexto de ejecución)Usos principalesOperaciones administrativas o complejasCálculos y operaciones que devuelven datos
¿Por qué usar stored procedures en PL/pgSQL?
- Centralización de lógica: Evitan replicar lógica de negocio en el lado del cliente.
- Eficiencia: Reducen el tráfico entre la aplicación y la base de datos.
- Seguridad: Ocultan detalles de las tablas y columnas.
- Flexibilidad: Perfectas para operaciones administrativas complejas y tareas repetitivas.
Los stored procedures en PL/pgSQL son herramientas poderosas que facilitan la creación de sistemas robustos, eficientes y fáciles de mantener.