En muchos lenguajes de programación, casi no hay diferencia entre funciones y procedimientos. En SQL sí la hay. En PostgreSQL, funciones y procedimientos no son solo dos formas distintas de ejecutar código. Son paradigmas de pensamiento diferentes.
Una función en SQL no puede modificar datos en la base de datos. Solo debe trabajar con los datos que recibe y devolver un resultado basado en ellos. Se crea para usarse dentro de consultas SELECT.
Un procedimiento en SQL está hecho para modificar la base. Por eso puede trabajar con transacciones (a diferencia de las funciones), escribir cosas en la base. Y no puede usarse dentro de consultas SELECT.
Aquí tienes una comparación rápida:
| Característica | Función (FUNCTION) | Procedimiento (PROCEDURE) |
|---|---|---|
| Devuelve datos | ✅ Sí (RETURNS ...) |
❌ No (solo puede ejecutar acciones) |
| Se llama mediante | SELECT, PERFORM |
CALL |
| Se puede usar en consultas | ✅ Sí | ❌ No |
Puede estar en DO |
✅ Sí | ❌ No |
Soporta COMMIT, ROLLBACK |
❌ No | ✅ Sí |
| Incluido en PostgreSQL | Desde el principio | Desde la versión 11 |
Diferencias en SQL
En SQL normal, una función se parece a una expresión: calcula y devuelve un valor. Un procedimiento es una instrucción: hace algo, pero no participa en expresiones.
Función en SQL
SELECT calculate_discount(200);
- Puedes usarla en
WHERE,ORDER BY,INSERT,UPDATE, etc. - Debe ser pura: no debe cambiar el estado de la base (si es IMMUTABLE/STABLE).
Procedimiento en SQL
CALL process_order(123);
- No devuelve resultado.
- Puedes hacer
COMMIT,ROLLBACK, llamar aRAISE, ejecutar bucles.
Diferencias en PL/pgSQL
Las funciones en PostgreSQL se pueden ver como un grupo de cálculos. Son muy flexibles: puedes pasar parámetros, usar condicionales, bucles, cursores, subconsultas, devolver filas, escalares, tablas.
Funciones en PL/pgSQL
CREATE FUNCTION square(x INT) RETURNS INT AS $$
BEGIN
RETURN x * x;
END;
$$ LANGUAGE plpgsql;
Características:
RETURNSes obligatorio- Puedes usar
DECLARE,BEGIN,END,LOOP,IF,CASE - No puedes hacer
COMMIT/ROLLBACK - Puedes llamarla en
SELECT,UPDATE,CHECK,WHERE,RETURNING
Llamada:
SELECT square(5); -- devolverá 25
Procedimientos en PL/pgSQL
Los procedimientos son un mecanismo para gestionar acciones. Son perfectos cuando necesitas:
- hacer muchos pasos con lógica;
- actualizar e insertar grandes volúmenes de datos;
- usar gestión de transacciones:
COMMIT,ROLLBACK,SAVEPOINT.
CREATE PROCEDURE log_event(msg TEXT) AS $$
BEGIN
INSERT INTO logs(message) VALUES (msg);
COMMIT;
END;
$$ LANGUAGE plpgsql;
Características:
- No tiene
RETURNS - Solo se llama con
CALL - Se permite usar
COMMIT,ROLLBACK,SAVEPOINT - Ideal para procesos por lotes, migraciones, ETL
Llamada:
CALL log_event('Procesamiento terminado');
¿Por qué están separadas funciones y procedimientos?
Porque tienen objetivos diferentes en SQL:
| Funciones | Procedimientos |
|---|---|
| "Calcular algo y devolverlo" | "Hacer algo y no devolver resultado" |
| Llamada desde SQL | Llamada como comando |
| No pueden gestionar transacciones | Pueden gestionar transacciones |
Se usan en SELECT, JOIN, WHERE |
Se usan en CALL, scripts |
La ventaja clave del procedimiento — COMMIT
Los procedimientos pueden gestionar transacciones dentro de sí mismos. O sea, dentro del procedimiento puedes hacer:
BEGIN;
-- lógica
SAVEPOINT point1;
-- intento de actualización
ROLLBACK TO point1;
COMMIT;
Y en una función COMMIT y ROLLBACK están prohibidos. Si lo intentas, te sale: ERROR: invalid transaction termination in function
Esto significa que una función debe ser determinista y segura, mientras que un procedimiento puede hacer "trabajo sucio": limpiar, registrar, insertar.
Tabla comparativa
| Característica | FUNCTION |
PROCEDURE |
|---|---|---|
| Devuelve valor | ✅ RETURNS |
❌ |
Se usa en SELECT |
✅ | ❌ |
| Llamada | SELECT, PERFORM, DO |
Solo CALL |
| Puedes usar en trigger | ✅ | ❌ (solo funciones) |
Transacciones dentro (COMMIT) |
❌ Prohibido | ✅ Permitido |
| Uso de parámetros OUT | Con RETURNS TABLE, RECORD |
Con parámetros OUT directamente |
| Ideal para cálculos | ✅ | 🚫 no es para eso |
| Ideal para ETL, carga | 🚫 limitado | ✅ perfecto |
| Puedes usar cursores | ✅ Sí | ✅ Sí |
¿Cuándo usar cada uno?
Usa una función si:
- quieres un valor de retorno;
- la llamas en
SELECT, filtras datos; - es un cálculo simple, una comprobación o un wrapper para SQL.
Usa un procedimiento si:
- quieres ejecutar acciones complejas;
- necesitas control de transacciones;
- procesas lotes, mueves datos, archivas, registras logs.
GO TO FULL VERSION