¿Alguna vez repetiste el mismo cálculo o lógica en varias consultas SQL?
En esos casos, las funciones definidas por el usuario (UDF, por sus siglas en inglés) son tu mejor aliada.
Las UDF permiten encapsular lógica personalizada dentro del propio motor de base de datos, de modo que puedas reutilizar código, simplificar consultas y mantener consistencia en tus operaciones.
En este artículo aprenderás qué son, cómo se crean y cuándo conviene usarlas —con ejemplos prácticos en PostgreSQL, que puedes ejecutar en db-fiddle.com.
¿Qué es una UDF?
Una User Defined Function (UDF) es una función creada por el usuario para realizar una operación específica que no está incluida entre las funciones nativas del motor de base de datos.
Por ejemplo:
- Calcular impuestos o descuentos personalizados.
- Formatear textos o fechas con reglas específicas.
- Encapsular operaciones complejas que se repiten en distintas consultas.
Ejemplo básico: función para calcular impuestos
Supongamos que tenemos una tabla de ventas y queremos calcular el monto total con IVA (16%).
CREATE TABLE ventas (
venta_id SERIAL PRIMARY KEY,
producto TEXT,
subtotal NUMERIC
);
INSERT INTO ventas (producto, subtotal) VALUES
('Laptop', 12000),
('Teclado', 800),
('Monitor', 5000); En lugar de escribir el cálculo del IVA cada vez, podemos crear una función:
CREATE OR REPLACE FUNCTION calcular_total_iva(_subtotal NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
RETURN _subtotal * 1.16;
END;
$$ LANGUAGE plpgsql; Ahora puedes usarla en cualquier consulta:
SELECT producto,
subtotal,
calcular_total_iva(subtotal) AS total_con_iva
FROM ventas; Resultado:
| producto | subtotal | total_con_iva |
|---|---|---|
| Laptop | 12000.00 | 13920.00 |
| Teclado | 800.00 | 928.00 |
| Monitor | 5000.00 | 5800.00 |
💡 Ventaja: si el IVA cambia, solo modificas la función, no todas las consultas.
Ejemplo intermedio: función condicional
También puedes incluir lógica más avanzada, como descuentos:
CREATE OR REPLACE FUNCTION calcular_precio_final(_subtotal NUMERIC, _descuento NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
total NUMERIC;
BEGIN
total := _subtotal - (_subtotal * _descuento / 100);
RETURN total * 1.16;
END;
$$ LANGUAGE plpgsql; Y usarla así:
SELECT producto,
subtotal,
calcular_precio_final(subtotal, 10) AS total_final
FROM ventas; Tipos de funciones en PostgreSQL
- Funciones escalares → devuelven un valor (como los ejemplos anteriores).
- Funciones de tabla (table-valued) → devuelven un conjunto de filas.
- Funciones de agregación personalizadas → aplican sobre grupos de registros.
Ejemplo de función que devuelve una tabla:
CREATE OR REPLACE FUNCTION ventas_mayores_a(_minimo NUMERIC)
RETURNS TABLE(producto TEXT, subtotal NUMERIC) AS $$
BEGIN
RETURN QUERY
-- Usamos 'v' como alias para la tabla 'ventas'
SELECT v.producto, v.subtotal FROM ventas v
WHERE v.subtotal > _minimo;
END;
$$ LANGUAGE plpgsql; Llamada:
SELECT * FROM ventas_mayores_a(1000); Buenas prácticas para crear UDF
- Prefiere nombres claros y consistentes:
fn_oudf_al inicio (ej.fn_calcular_total). - Usa
IMMUTABLEoSTABLEcuando la función no modifica datos (optimiza el rendimiento). - Evita operaciones de escritura dentro de una función (usa procedimientos en su lugar).
- Documenta la lógica interna de cada UDF.
Diferencias entre motores SQL
| Motor | Lenguaje | Sintaxis | Notas |
|---|---|---|---|
| PostgreSQL | PL/pgSQL | Muy flexible | Soporta funciones de tabla |
| SQL Server | T-SQL | Usa CREATE FUNCTION | Puede devolver tablas y valores escalares |
| MySQL | SQL/PSM | Menos flexible | Las funciones no pueden modificar tablas |
| SQLite | N/A | Requiere extensión o código externo | Ideal para funciones simples en Python/C |
Conclusión
Las UDF te permiten escribir SQL más limpio, reutilizable y profesional.
Cuando las integras adecuadamente, tu base de datos se convierte en una herramienta capaz de automatizar cálculos complejos y centralizar la lógica de negocio.