Depuración PostgreSQL
Los desencadenantes PostgreSQL son funciones de devolución de llamada de la base de datos que se ejecutan o "desencadenan" automáticamente cuando se produce un evento especificado de la base de datos, como un `INSERT`, `UPDATE`, `DELETE` o `TRUNCATE`. Se utilizan para mantener la integridad de los datos, aplicar normas empresariales o realizar registros y auditorías.
Utilización
Los desencadenantes se utilizan cuando necesitas automatizar tareas en respuesta a cambios en los datos de una tabla. Son especialmente útiles para mantener la coherencia y aplicar una lógica empresarial compleja a nivel de base de datos.
sql
CREATE TRIGGER trigger_name
{ BEFORE | AFTER | INSTEAD OF }
{ INSERT | UPDATE | DELETE | TRUNCATE }
ON table_name
[ FOR EACH ROW | FOR EACH STATEMENT ]
EXECUTE PROCEDURE function_name();
En esta sintaxis, `CREATE TRIGGER` define un nuevo activador llamado `trigger_name`, especificando cuándo debe activarse (`BEFORE`, `AFTER` o `INSTEAD OF`), qué evento debe activarlo (`INSERT`, `UPDATE`, `DELETE` o `TRUNCATE`) y la tabla a la que se aplica (`ON table_name`). EJECUTAR PROCEDIMIENTO" llama a la función que contiene la lógica de activación.
Ejemplos
1. Disparo básico al insertar
sql
CREATE OR REPLACE FUNCTION log_insert()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO log_table(action, timestamp) VALUES ('INSERT', NOW());
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER insert_trigger
AFTER INSERT ON main_table
FOR EACH ROW
EXECUTE PROCEDURE log_insert();
Este ejemplo crea un activador que registra una entrada en `tabla_log` cada vez que se inserta una nueva fila en `tabla_principal`.
2. Activador para aplicar la norma empresarial
sql
CREATE OR REPLACE FUNCTION check_salary()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.salary < 1000 THEN
RAISE EXCEPTION 'Salary cannot be less than 1000';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER salary_check
BEFORE INSERT OR UPDATE ON employees
FOR EACH ROW
EXECUTE PROCEDURE check_salary();
Aquí, un activador garantiza que el salario de cualquier empleado no se establezca por debajo de 1000, ni en la inserción ni en la actualización.
3. Activador del registro de auditoría
sql
CREATE OR REPLACE FUNCTION audit_changes()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
INSERT INTO audit_log(table_name, operation, old_data, new_data, changed_at)
VALUES (TG_TABLE_NAME, TG_OP, ROW(OLD.*), ROW(NEW.*), NOW());
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER audit_trigger
AFTER UPDATE ON any_table
FOR EACH ROW
EXECUTE PROCEDURE audit_changes();
Este ejemplo captura los cambios en `cualquier_tabla` registrando los datos de las filas antiguas y nuevas en una tabla `audit_log` después de cada actualización.
Gestionar desencadenantes
Para desactivar un activador:
sql
ALTER TABLE table_name DISABLE TRIGGER trigger_name;
Para activar un activador:
sql
ALTER TABLE table_name ENABLE TRIGGER trigger_name;
Para eliminar un activador:
sql
DROP TRIGGER trigger_name ON table_name;
Consejos y buenas prácticas
- Mantén los activadores simples y eficientes. Una lógica compleja puede ralentizar las operaciones de la base de datos. Ten cuidado con las implicaciones para el rendimiento, especialmente en entornos altamente transaccionales.
- Utiliza activadores para las restricciones críticas. Asegúrate de que las reglas empresariales críticas se aplican a nivel de base de datos.
- Limita los efectos secundarios. Los desencadenantes deben evitar alterar el estado de la base de datos de forma inesperada.
- Activadores de documentos. Mantén una documentación clara de cada activador para ayudar a los futuros programadores a comprender su finalidad.
- Prueba a fondo. Asegúrate de que los activadores funcionan como se espera probándolos con diversos escenarios y casos extremos.
- Ten en cuenta el orden de ejecución. Comprende el orden de ejecución cuando se definen varios desencadenantes para el mismo evento en una tabla.
- Gestiona las llamadas recursivas. Sé consciente de las posibles llamadas desencadenantes recursivas e implanta salvaguardas cuando sea necesario.