Disparadores a nivel de sentencia PostgreSQL
Los disparadores en PostgreSQL son procedimientos especiales que se ejecutan o disparan automáticamente cuando se producen determinados eventos en una tabla de la base de datos. Los disparadores a nivel de sentencia se ejecutan una vez por sentencia SQL, independientemente del número de filas afectadas por la sentencia.
Utilización
Los disparadores a nivel de sentencia se utilizan para aplicar reglas de negocio, validar entradas o mantener registros de auditoría cuando una sentencia afecta a cualquier número de filas. Se definen para actuar antes o después de las operaciones `INSERT`, `UPDATE` o `DELETE` en una tabla.
sql
CREATE TRIGGER trigger_name
{ BEFORE | AFTER } { INSERT | UPDATE | DELETE }
ON table_name
FOR EACH STATEMENT
EXECUTE PROCEDURE function_name();
En esta sintaxis, "PARA CADA DECLARACIÓN" especifica que el activador debe dispararse una vez por cada declaración, y "EJECUTAR PROCEDIMIENTO" define la función que debe invocarse. Ten en cuenta que los activadores a nivel de sentencia no tienen acceso a los valores de fila `OLD` y `NEW`, ya que no son específicos de cada fila.
Ejemplos
1. Activador básico a nivel de enunciado
sql
-- This function logs an entry into audit_log whenever an INSERT, UPDATE, or DELETE operation is performed on the employees table.
CREATE FUNCTION log_total_changes() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit_log(event_type, event_time)
VALUES (TG_OP, now());
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER audit_changes
AFTER INSERT OR UPDATE OR DELETE
ON employees
FOR EACH STATEMENT
EXECUTE PROCEDURE log_total_changes();
2. Activador de operaciones de inserción
sql
-- This function logs every INSERT operation on the employees table into the insert_log table with the current timestamp.
CREATE FUNCTION log_inserts() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO insert_log(table_name, insert_time)
VALUES (TG_TABLE_NAME, now());
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER log_employee_inserts
AFTER INSERT
ON employees
FOR EACH STATEMENT
EXECUTE PROCEDURE log_inserts();
3. Ejecución condicional del activador
sql
-- This function conditionally calls a notification function only when a DELETE operation is performed on the orders table.
CREATE FUNCTION notify_admin() RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
PERFORM notify_admin_function();
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER admin_notification
AFTER DELETE
ON orders
FOR EACH STATEMENT
EXECUTE PROCEDURE notify_admin();
En estos ejemplos, `TG_OP` se refiere al tipo de operación (`INSERT`, `UPDATE` o `DELETE`), y `TG_TABLE_NAME` se refiere al nombre de la tabla en la que está definido el activador.
Consejos y buenas prácticas
- Limita la complejidad del activador. Mantén la lógica de activación simple para evitar efectos secundarios no deseados y mantener el rendimiento.
- Utiliza los desencadenantes con moderación. Un uso excesivo puede provocar problemas de mantenimiento y dificultar la depuración.
- Documenta claramente los desencadenantes. Documenta siempre la finalidad y la función de los activadores en tu base de datos.
- Prueba a fondo. Asegúrate de que los activadores se prueban a fondo para validar su comportamiento en distintos escenarios.
- Considera el impacto en el rendimiento. Ten en cuenta que los activadores pueden afectar al rendimiento, especialmente en entornos con muchas transacciones.
- Considera la posibilidad de utilizar activadores a nivel de fila para la lógica específica de cada fila. Los desencadenadores a nivel de sentencia no son adecuados para operaciones específicas de fila, así que utiliza desencadenadores a nivel de fila cuando sea necesario.
- Comprende las diferencias de activación. Los desencadenantes a nivel de sentencia se ejecutan una vez por sentencia sin acceso a filas específicas, mientras que los desencadenantes a nivel de fila se ejecutan para cada fila afectada y pueden acceder a los valores de fila `OLD` y `NEW`.