Si alguna vez te encontraste con una situación donde necesitas ejecutar alguna acción para cada fila durante una actualización masiva de datos o solo una vez para toda la tabla, probablemente te hayas preguntado: ¿cómo es mejor hacerlo? PostgreSQL te da dos opciones: triggers a nivel de fila y triggers a nivel de operación. Entender cuándo usar cada uno es clave para diseñar bien tu base de datos, optimizar su rendimiento y evitar errores. ¡Vamos a verlo!
Los triggers que funcionan a nivel de fila (FOR EACH ROW) se disparan cada vez para cada fila afectada por una operación INSERT, UPDATE o DELETE. O sea, si tu consulta SQL afecta a 100 filas, el trigger se ejecuta 100 veces.
¿Cuándo usarlos?
Los triggers a nivel de fila son útiles si necesitas procesar cada fila modificada de forma individual. Por ejemplo:
- Registrar los cambios de cada fila.
- Actualizar automáticamente datos relacionados para cada fila.
Ejemplo: registrar cambios para cada fila
Supón que tienes una tabla de estudiantes:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Queremos registrar cada fila que se actualiza en esta tabla en otra tabla students_log:
CREATE TABLE students_log (
log_id SERIAL PRIMARY KEY,
student_id INT,
old_name VARCHAR(100),
new_name VARCHAR(100),
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Función para registrar los cambios:
CREATE OR REPLACE FUNCTION log_student_update()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO students_log(student_id, old_name, new_name, changed_at)
VALUES (OLD.id, OLD.name, NEW.name, CURRENT_TIMESTAMP);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Creando el trigger FOR EACH ROW:
CREATE TRIGGER student_update_logger
AFTER UPDATE ON students
FOR EACH ROW
EXECUTE FUNCTION log_student_update();
Probando:
UPDATE students
SET name = 'Iván Ivanov'
WHERE id = 1;
Después de ejecutar esta consulta, en la tabla students_log aparecerá un registro con los detalles del cambio.
Triggers a nivel de operación (FOR EACH STATEMENT)
Los triggers a nivel de operación (FOR EACH STATEMENT) se disparan una sola vez por toda la consulta SQL, sin importar cuántas filas se vean afectadas. Si la consulta actualiza 100 filas, el trigger se ejecuta solo una vez.
Los triggers a nivel de operación son útiles si necesitas:
- Ejecutar una acción solo una vez por toda la operación.
- Trabajar con datos agregados o hacer cálculos para toda la tabla.
Ejemplo: actualizar un contador de cambios
Supón que tienes una tabla de contador de cambios para la tabla students:
CREATE TABLE students_changes_log (
total_changes INT DEFAULT 0
);
INSERT INTO students_changes_log(total_changes) VALUES (0);
Queremos incrementar el valor de este contador cada vez que se hace un UPDATE en la tabla students.
Función para actualizar el contador:
CREATE OR REPLACE FUNCTION increment_changes_counter()
RETURNS TRIGGER AS $$
BEGIN
UPDATE students_changes_log
SET total_changes = total_changes + 1;
RETURN NULL; -- Un trigger a nivel de operación no devuelve filas
END;
$$ LANGUAGE plpgsql;
Creando el trigger FOR EACH STATEMENT:
CREATE TRIGGER update_changes_counter
AFTER UPDATE ON students
FOR EACH STATEMENT
EXECUTE FUNCTION increment_changes_counter();
Probando:
UPDATE students
SET age = age + 1
WHERE age < 20;
Después de ejecutar la consulta el trigger se disparará una sola vez y el contador de cambios aumentará en uno.
Comparación FOR EACH ROW y FOR EACH STATEMENT
| Criterio | FOR EACH ROW | FOR EACH STATEMENT |
|---|---|---|
| Nivel de ejecución | Para cada fila afectada | Una vez por toda la operación |
| Frecuencia de llamada | Una llamada por fila | Una llamada por consulta SQL |
| Tareas | Registro de cambios individuales, procesamiento de filas | Agregación, actualización de metainformación |
| Ejemplo | Registro de cambios para cada fila | Actualizar contador de cambios |
| Rendimiento | Más costoso en operaciones masivas | Menos costoso para operaciones masivas |
¿Cuándo usar FOR EACH ROW y FOR EACH STATEMENT?
Usa FOR EACH ROW si:
- Quieres que el trigger se ejecute para cada fila.
- La lógica de ejecución debe estar ligada a los cambios de filas concretas.
- Necesitas acceder a los datos
OLDyNEWde cada fila.
Ejemplo: Registrar cambios en la tabla o crear automáticamente registros relacionados.
Usa FOR EACH STATEMENT si:
- Quieres ejecutar una acción solo una vez por toda la operación.
- La lógica del trigger no depende de los cambios de filas concretas.
- El rendimiento es crítico y no quieres que el trigger se dispare muchas veces.
Ejemplo: Actualizar contadores, calcular metadatos para la tabla.
Errores y puntos importantes
Usar el tipo correcto de trigger puede no ser tan obvio, así que ojo con esto:
- Uno de los errores más comunes es intentar usar los datos
OLDyNEWen un triggerFOR EACH STATEMENT. Esto dará error porque esas variables solo existen en triggers a nivel de fila. - Los triggers a nivel de fila (
FOR EACH ROW) pueden ralentizar mucho las operaciones si la consulta afecta a muchas filas. Siempre ten en cuenta el rendimiento. - Ten cuidado con la recursividad de los triggers. Por ejemplo, si un trigger modifica datos en la misma tabla, puedes acabar en un bucle infinito.
GO TO FULL VERSION