Llamada a funciones desde consultas SQL
Imagina que tienes una función para cálculos complejos o procesamiento de datos. Sin la posibilidad de integrar la función en las consultas SQL, trabajarías así:
- Llamarías a la función desde algún lenguaje de programación (por ejemplo, Python o JavaScript).
- Pasarías el resultado a la consulta SQL.
¡Eso es un paso de más! En PostgreSQL puedes meter funciones directamente en la consulta SQL, recortando código, acelerando operaciones y reduciendo llamadas al servidor. Esto es especialmente útil para:
- Automatizar cálculos.
- Validar datos antes de insertar.
- Modificar datos existentes.
Llamar funciones en SELECT
Vamos con lo básico y veamos cómo usar funciones en una consulta SELECT normal. Supón que tienes una tabla students con info de estudiantes. Queremos escribir una función que devuelva la edad actual del estudiante según su fecha de nacimiento.
Paso 1: escribir la función
Vamos a crear la función calculate_age, que recibe la fecha de nacimiento y devuelve la edad:
CREATE OR REPLACE FUNCTION calculate_age(birth_date DATE) RETURNS INT AS $$
BEGIN
RETURN DATE_PART('year', AGE(NOW(), birth_date))::INT;
END;
$$ LANGUAGE plpgsql;
Paso 2: usar la función en la consulta SELECT
Ahora podemos llamar a esta función para cada registro de la tabla:
SELECT id, name, calculate_age(birth_date) AS age FROM students;
¿Qué pasa aquí?
- Para cada fila de la tabla
students, la funcióncalculate_agecalcula la edad. - El valor devuelto aparece en la columna
age.
Ejemplo de resultado:
| id | name | age |
|---|---|---|
| 1 | Otto | 21 |
| 2 | Anna | 25 |
| 3 | Aleks | 22 |
Como ves, no tiene misterio y el resultado queda guay y profesional.
Llamar funciones en INSERT
Las funciones también molan cuando insertas datos. Por ejemplo, imagina que tienes una tabla logs donde se guardan acciones de usuarios. Queremos insertar un mensaje de log usando una función que genere el texto automáticamente.
Paso 1: crear la función
Escribimos la función generate_log_message, que recibe el nombre de usuario y la acción, y devuelve el texto del mensaje:
CREATE OR REPLACE FUNCTION generate_log_message(username TEXT, action TEXT) RETURNS TEXT AS $$
BEGIN
RETURN username || ' realizó acción: ' || action || ' en ' || NOW();
END;
$$ LANGUAGE plpgsql;
Paso 2: usar la función en INSERT
Ahora insertamos el mensaje en la tabla logs llamando a la función al añadir la fila:
INSERT INTO logs (message)
VALUES (generate_log_message('Otto', 'inicio de sesión'));
Resultado:
| id | message |
|---|---|
| 1 | Otto realizó acción: inicio de sesión en 2023-10-26 12:00:00 |
La función lo hace todo: se encarga del formato y añade la marca de tiempo. Es un ejemplo top de cómo las funciones pueden automatizar tareas rutinarias.
Llamar funciones en UPDATE
Las funciones también sirven para modificar datos en una tabla. Supón que tienes la tabla students y quieres actualizar el nombre del grupo usando una función para pasarlos al siguiente curso.
Paso 1: crear la función
Escribimos la función promote_student, que recibe el grupo antiguo (por ejemplo, 101) y devuelve el nuevo (por ejemplo, 201):
CREATE OR REPLACE FUNCTION promote_student(old_group TEXT) RETURNS TEXT AS $$
BEGIN
RETURN '2' || RIGHT(old_group, LENGTH(old_group) - 1);
END;
$$ LANGUAGE plpgsql;
Paso 2: usar la función en UPDATE
Actualizamos el grupo de todos los estudiantes:
UPDATE students
SET group_name = promote_student(group_name);
Resultado:
| id | name | group_name |
|---|---|---|
| 1 | Otto | 201 |
| 2 | Anna | 202 |
| 3 | Aleks | 203 |
Mira cómo la función hace la magia de actualizar: los grupos viejos se transforman en nuevas cadenas.
Llamar funciones en condiciones WHERE
Las funciones pueden usarse en condiciones de filtrado. Vamos a ampliar el ejemplo de la edad de los estudiantes.
Paso 1: filtrar por edad
Usamos la función calculate_age que ya hicimos para seleccionar estudiantes mayores de 20 años:
SELECT id, name, birth_date
FROM students
WHERE calculate_age(birth_date) > 20;
Resultado:
| id | name | birth_date |
|---|---|---|
| 2 | Anna | 1998-05-15 |
| 3 | Aleks | 1999-11-09 |
Aquí la función se encarga de calcular la edad de cada estudiante al vuelo.
Combinando con funciones agregadas
Vamos a complicarlo un poco. Necesitamos contar el número total de estudiantes menores de 22 años. Las funciones van de lujo con funciones agregadas como COUNT().
SELECT COUNT(*)
FROM students
WHERE calculate_age(birth_date) < 22;
¿Qué pasa aquí?
- La función
calculate_agese usa en el filtrado. COUNT(*)cuenta las filas que cumplen la condición.
Ejemplos reales de uso
Automatización de validación de datos. Supón que quieres comprobar que la edad de todos los estudiantes está en un rango típico (por ejemplo, de 18 a 30 años). Escribe una función para comprobarlo y úsala en la condición WHERE.
SELECT id, name
FROM students
WHERE NOT (calculate_age(birth_date) BETWEEN 18 AND 30);
Optimización de inserción de datos. Imagina que trabajas en una tienda online. En vez de calcular el precio total del pedido en el cliente, escribe una función que lo calcule directamente al añadir datos en la tabla orders.
INSERT INTO orders (user_id, total_price)
VALUES (1, calculate_total_price(ARRAY[5, 10, 15]));
Errores típicos al llamar funciones
Cuando empieces a usar funciones a tope en las consultas, pueden salir errores. Aquí tienes algunas situaciones comunes y cómo arreglarlas:
Falta de permisos necesarios. Si no eres el dueño de la función o la tabla, PostgreSQL puede bloquear la llamada. Asegúrate de tener permisos para ejecutar la función.
Desajuste de tipos. Cuando pases argumentos a la función, fíjate en los tipos de datos. Por ejemplo, si la función espera DATE y le pasas una cadena, te dará error. Usa conversión explícita:
SELECT calculate_age('2000-01-01'::DATE);
Errores de sintaxis dentro de funciones. Si la función devuelve un error, puede romper toda la consulta. Prueba bien las funciones antes de usarlas.
GO TO FULL VERSION