BD II · Procedimientos y Triggers
🗄️ Guía de Aula Invertida

Procedimientos, Funciones y Triggers

Hasta ahora cada consulta SQL vivía sola: si la misma lógica (un cálculo, una validación) se repite en diez consultas distintas, hay que mantenerla en diez lugares. Las funciones y procedimientos almacenados guardan esa lógica una sola vez, adentro de la propia base de datos. Los triggers van un paso más allá: ejecutan código automáticamente cuando algo pasa —un INSERT, un UPDATE— sin que nadie tenga que acordarse de llamarlos.

👁 vistas · Ing. Roy Carrasco, Facultad de Ingeniería de Sistemas · UAB

Scrollea para empezar — a la izquierda vas a ver la consulta y su resultado armarse solos, mientras leés a la derecha.

bd2 · procedimientos_triggers.sqlPaso 1 / 7
consulta.sql
-- todavía no escribimos nada
Paso 01 · El problema

La misma fórmula, repetida en cada consulta

Cada vez que una consulta necesita el precio final con IVA (13%), hay que escribir precio * 1.13 de nuevo. Si el porcentaje de IVA cambia algún día, hay que salir a buscar cada consulta que lo usa, una por una.

Paso 02 · CREATE FUNCTION

Guardar la fórmula una sola vez

Una función guarda esa lógica adentro de la base de datos, con un nombre propio. RETURNS NUMERIC dice qué tipo de dato devuelve; el cuerpo entre $$ ... $$ está escrito en PL/pgSQL, el lenguaje procedural de PostgreSQL.

Paso 03 · Llamarla como cualquier función

Se usa igual que ROUND() o LOWER()

Una vez creada, calcular_precio_final(precio) se llama exactamente como cualquier función de PostgreSQL —adentro de un SELECT, pasándole el nombre de una columna como argumento.

Paso 04 · IF / ELSIF / ELSE

Una función también puede decidir

PL/pgSQL soporta las mismas estructuras que ya conocés de otros lenguajes. clasificar_stock(cantidad) devuelve un texto distinto según en qué rango cae el argumento que recibe.

Paso 05 · Usarla en el SELECT

Una columna calculada, con lógica adentro

Igual que en el paso 03, la función se llama desde el SELECT —solo que esta vez devuelve un texto distinto según el valor de stock de cada fila.

Paso 06 · CREATE PROCEDURE

Cuando no hace falta devolver nada

Un procedimiento no tiene RETURNS: no devuelve un valor para usar en un SELECT, sino que ejecuta una acción —acá, un UPDATE. Se define con CREATE PROCEDURE, no CREATE FUNCTION.

Paso 07 · CALL

Se ejecuta con CALL, no con SELECT

Un procedimiento se invoca con CALL, nunca adentro de un SELECT —justamente porque no devuelve nada que se pueda leer ahí. Acá actualiza el precio del producto 2 directamente en la tabla.

Practicá lo que viste

Antes de seguir a triggers, confirmá que la diferencia entre función y procedimiento quedó clara.

Selección múltiple

¿Cuál es la diferencia real entre una función y un procedimiento almacenado?

Completar

Sobre la sintaxis de CREATE FUNCTION y CREATE PROCEDURE.

1. El cuerpo de una función o procedimiento en PL/pgSQL se escribe entre .

2. Para invocar un procedimiento (no una función), se usa la instrucción .

Clasificación

Clasifica cada elemento según si pertenece a una función o a un procedimiento.

RETURNS NUMERIC
Se invoca con CALL nombre(...)
Se usa dentro de un SELECT
CREATE PROCEDURE nombre(...)

bd2 · procedimientos_triggers.sqlPaso 1 / 7
consulta.sql
-- todavía no escribimos nada
Paso 01 · El problema

Nadie se acuerda de auditar a mano

Cada vez que alguien actualiza el stock de un producto, en teoría también debería insertar una fila en una tabla de auditoría, a mano, en la misma transacción. Tarde o temprano, alguien se va a olvidar.

Paso 02 · La tabla de auditoría

Dónde va a quedar el registro

Una tabla normal, sin nada especial todavía: auditoria_stock va a guardar qué producto cambió, cuánto stock tenía antes, cuánto tiene ahora, y cuándo.

Paso 03 · La función del trigger

OLD y NEW: la fila antes y después

Una función pensada para un trigger devuelve TRIGGER, no un tipo de dato normal. Adentro tiene acceso a dos filas especiales: OLD (la fila antes del cambio) y NEW (la fila después). Acá inserta ambos valores de stock en la auditoría.

Paso 04 · CREATE TRIGGER

Conectar la función a un evento

AFTER UPDATE ON productos dice cuándo se dispara: después de un UPDATE en esa tabla. FOR EACH ROW dice que corre una vez por cada fila afectada. WHEN (OLD.stock IS DISTINCT FROM NEW.stock) es un filtro extra: solo si el stock realmente cambió —no en cualquier UPDATE.

Paso 05 · Mirá esto

Nadie llamó a la función. Pasó sola.

Este UPDATE no menciona ni registrar_cambio_stock() ni auditoria_stock en ningún lado. Aun así, al consultar la auditoría después, ya hay una fila nueva —el trigger se disparó solo, apenas cambió el stock.

Paso 06 · BEFORE, no AFTER

Un trigger también puede impedir algo

AFTER reacciona a un cambio que ya pasó. BEFORE INSERT corre antes de que la fila se guarde, y con RAISE EXCEPTION puede cancelar la operación por completo si algo no es válido —acá, un precio que no sea mayor a 0.

Paso 07 · La inserción que no pasa

El INSERT nunca llega a guardarse

Este intento de insertar un producto con precio negativo no inserta nada: el trigger BEFORE INSERT corre primero, evalúa la condición, y frena la operación entera con el error que definiste en RAISE EXCEPTION.

Practicá lo que viste

Emparejá cada pieza de un trigger con lo que hace, y confirmá por qué el WHEN importa.

Emparejamiento

Une cada término con su descripción.

Selección múltiple

El trigger de auditoría tiene WHEN (OLD.stock IS DISTINCT FROM NEW.stock). Si alguien actualiza solo el precio de un producto (sin tocar el stock), ¿qué pasa?

Ejercicios de razonamiento

En estas preguntas no se te pide recordar sintaxis: se te da un escenario, y debés razonar cuál sería la respuesta correcta antes de comprobarla.

Escenario

Necesitás una operación que calcule el promedio de las notas de un estudiante y lo use directamente dentro de un SELECT, junto con otras columnas de la tabla.

Razonamiento

¿Función o procedimiento almacenado?

Otro escenario

Cada vez que se inserta un nuevo pedido, hay que descontar automáticamente esa cantidad del stock del producto correspondiente —sin que la aplicación tenga que acordarse de hacerlo aparte.

Razonamiento

¿Qué herramienta encaja mejor?

Un último escenario

Un compañero de equipo agregó un trigger BEFORE INSERT que valida datos, pero se queja de que "no anda": los INSERT inválidos se siguen guardando igual.

Completar

Completá la explicación que le darías:

Para que un trigger de validación de verdad impida guardar la fila, la función tiene que cuando el dato es inválido — de lo contrario, la fila se guarda igual aunque el trigger haya notado el problema.

Actividades de repaso

Un repaso integrador de todo el módulo. Cada actividad se corrige al instante; tu progreso se guarda automáticamente en este navegador.

0 / 0
actividades correctas en toda la guía
Selección múltiple

¿En qué lenguaje se escribe normalmente el cuerpo de una función o procedimiento en PostgreSQL?

Verdadero o falso

Un trigger se puede llamar directamente con SELECT registrar_cambio_stock(), igual que una función normal.

Selección múltiple

¿Qué diferencia hay entre un trigger BEFORE y uno AFTER?

Selección múltiple

¿Qué le pasa a un INSERT si un trigger BEFORE INSERT ejecuta RAISE EXCEPTION dentro de su función?

Selección múltiple

¿Para qué sirve específicamente la cláusula WHEN de un CREATE TRIGGER?

Cheat Sheet

FormaPara qué sirve
CREATE FUNCTION nombre(...) RETURNS tipo AS $$ ... $$ LANGUAGE plpgsql;Guardar lógica que devuelve un valor, usable en un SELECT.
CREATE PROCEDURE nombre(...) LANGUAGE plpgsql AS $$ ... $$;Guardar una acción que no devuelve valor, invocada con CALL.
CALL nombre(argumentos);Ejecutar un procedimiento almacenado.
IF ... THEN ... ELSIF ... ELSE ... END IF;Decidir qué hacer, adentro de PL/pgSQL.
RETURNS TRIGGERMarca que una función está pensada para usarse en un trigger, no para llamarse directo.
OLD / NEWLa fila antes y después del cambio, disponibles dentro de la función del trigger.
CREATE TRIGGER nombre BEFORE|AFTER evento ON tabla FOR EACH ROW EXECUTE FUNCTION funcion();Conectar una función de trigger a un evento de una tabla.
WHEN (condición)Filtro extra: el trigger solo se dispara si la condición es verdadera.
RAISE EXCEPTION 'mensaje';Detener la operación completa con un error, típico en un trigger BEFORE de validación.

¿Sabías que...?

🐘 PL/pgSQL no es el único lenguaje posible

PostgreSQL permite escribir funciones en otros lenguajes instalados como extensión: PL/Python, PL/Perl e incluso PL/Java. PL/pgSQL es el que viene incluido por defecto y el más usado, pero no es la única opción.

🔁 Un trigger puede disparar a otro trigger

Si el INSERT que hace un trigger dentro de su función activa, a su vez, otro trigger sobre esa segunda tabla, PostgreSQL sigue la cadena. Encadenar demasiados triggers entre sí puede volverse difícil de rastrear —y en un caso extremo, hasta generar una recursión infinita que Postgres corta con un límite de profundidad.

👁️ También existen los triggers INSTEAD OF

Una vista normal no siempre acepta INSERT/UPDATE/DELETE directo. Un trigger INSTEAD OF permite definir manualmente qué hacer cuando alguien intenta modificar una vista, traduciendo esa operación a cambios reales sobre las tablas de base.