Saltar al contenido

Disparadores

Código que el gestor ejecuta solo, sin que nadie lo llame, cuando ocurre un evento sobre una tabla: cuándo salta, con qué granularidad, cómo se escribe, qué datos ve y qué no puede hacer.

Qué es un disparador

Un disparador es un bloque de una o varias sentencias asociado a una tabla que el gestor ejecuta por su cuenta cuando ocurre un evento sobre ella. Se parece a un procedimiento en que contiene código procedural guardado en la base, y se diferencia en lo esencial: un procedimiento se llama y un disparador no. Nadie lo invoca; salta solo.

Esa es toda su gracia y todo su peligro. Como no depende de que la aplicación se acuerde de ejecutarlo, la regla se cumple siempre, venga el cambio de donde venga. Y como no aparece en el código de la aplicación, un efecto inesperado obliga a ir a buscarlo al catálogo del gestor. Los usos típicos son la auditoría de cambios, el mantenimiento de datos derivados y la validación de reglas que un CHECK no alcanza a expresar.

El procedimiento se ejecuta porque alguien lo llama; el disparador se ejecuta porque ha pasado algo. Esa es la frontera entre los dos.

Para el examen

  • Qué es: código asociado a una tabla que el gestor ejecuta ante un evento

  • Quién lo llama: nadie: se dispara solo

  • Usos típicos: auditoría, datos derivados y validaciones que un CHECK no alcanza

Cuándo salta: momento y evento

Al crear un disparador hay que decir dos cosas: en qué momento actúa respecto de la sentencia que lo provoca y qué evento lo provoca. El momento admite tres valores y el evento otros tres, y se combinan libremente.

MomentoCuándo se ejecutaPara qué se usa
BEFOREAntes de aplicar la sentenciaValidar o corregir los valores que van a entrar, y rechazar la operación si no procede
AFTERDespués de aplicar la sentenciaAuditar lo ocurrido y propagar el cambio a otras tablas, ya con los datos definitivos
INSTEAD OFEn lugar de la sentencia, que no llega a ejecutarseSustituir la operación por otra. Es lo que permite escribir sobre vistas que no serían actualizables

Los eventos son los tres que modifican datos: INSERT, UPDATE y DELETE. Un mismo disparador puede atender a más de uno. De la combinación de tres momentos con tres eventos salen las nueve posibilidades que se preguntan en el examen, aunque INSTEAD OF se reserva en la práctica a las vistas.

Conviene fijar bien el INSTEAD OF, porque es el que se falla: no añade nada a la sentencia original, la anula. Lo único que se ejecuta es el cuerpo del disparador. El ejemplo clásico es convertir un borrado en otra cosa, de modo que un DELETE sobre una tabla acabe insertando una fila en una tabla de auditoría y dejando el dato intacto.

Para el examen

  • BEFORE: validar o corregir antes

  • AFTER: auditar y propagar después

  • INSTEAD OF: anula la sentencia y solo ejecuta el cuerpo; típico de vistas

  • Eventos: INSERT, UPDATE y DELETE

Cuántas veces salta: fila o sentencia

La otra decisión es la granularidad, y decide el número de ejecuciones. Un disparador de fila, declarado con FOR EACH ROW, se ejecuta una vez por cada fila afectada. Uno de sentencia, declarado con FOR EACH STATEMENT, se ejecuta una sola vez por sentencia, sin importar a cuántas filas alcance.

El caso que lo aclara todo: un UPDATE que modifica cuarenta filas ejecuta cuarenta veces el disparador de fila y una sola vez el de sentencia. Y hay un detalle que se pregunta: si la sentencia no llega a afectar a ninguna fila, el de fila no se ejecuta ni una vez, mientras que el de sentencia se ejecuta igualmente, porque la sentencia sí ha ocurrido.

La elección no es de gusto. Para auditar el valor anterior y el nuevo de cada registro hace falta el de fila, porque es el único que ve los datos de la fila concreta. Para llevar un contador de operaciones o registrar que se ha ejecutado un mantenimiento basta el de sentencia, que además es mucho más barato.

FOR EACH ROW se ejecuta tantas veces como filas toque la sentencia; FOR EACH STATEMENT, una sola vez por sentencia, incluso si no toca ninguna fila.

Para el examen

  • FOR EACH ROW: una ejecución por fila afectada

  • FOR EACH STATEMENT: una por sentencia, aunque no toque ninguna fila

Escribir un disparador

En la creación se juntan las tres decisiones: el momento y el evento, la tabla a la que se asocia y la granularidad. El cuerpo va entre BEGIN y END, igual que el de un procedimiento.

sql
CREATE TRIGGER auditar_cambio_modalidad
AFTER UPDATE ON alumno
FOR EACH ROW
BEGIN
  INSERT INTO alumno_auditoria
         (id_alumno, modalidad_antes, modalidad_despues, cambiado_el)
  VALUES (OLD.id_alumno, OLD.modalidad, NEW.modalidad, CURRENT_TIMESTAMP);
END;

CREATE TRIGGER contar_purgas
AFTER DELETE ON intento
FOR EACH STATEMENT
BEGIN
  INSERT INTO purga_log (ejecutada_el) VALUES (CURRENT_TIMESTAMP);
END;

Dentro del cuerpo de un disparador de fila el gestor pone a disposición los valores de la fila afectada: OLD guarda cómo estaba antes y NEW cómo queda después. Con los dos delante se puede registrar exactamente qué cambió, que es lo que hace el primer ejemplo. El segundo no necesita ninguno de los dos, porque solo anota que hubo una purga.

Para el examen

  • Qué reúne CREATE TRIGGER: momento, evento, tabla y granularidad

  • Cuerpo: entre BEGIN y END

  • OLD y NEW: el antes y el después, en los disparadores de fila

Las pseudotablas OLD y NEW

Los valores anterior y posterior de la fila se ofrecen a través de unas estructuras que no existen en el esquema y que solo son visibles dentro del disparador. Cada fabricante las nombra a su manera, y esa correspondencia es material de examen.

Momento del datoOracle y PostgreSQLSQL Server
Valor anterior al cambioOLDDELETED
Valor posterior al cambioNEWINSERTED

No siempre están disponibles las dos, y el criterio es simple: existe la que tiene sentido. En un INSERT no hay valor anterior, así que solo hay NEW. En un DELETE no hay valor posterior, así que solo hay OLD. En un UPDATE existen las dos, porque hay un antes y un después. Intentar leer la que no corresponde es un error frecuente.

Hay además una asimetría entre momentos que conviene conocer: en un disparador BEFORE se pueden modificar los valores de NEW y con ello alterar lo que finalmente se graba, mientras que en un AFTER el cambio ya está hecho y NEW es solo de lectura.

Para el examen

  • Nombres en SQL Server: DELETED e INSERTED

  • En un INSERT: solo existe NEW

  • En un DELETE: solo existe OLD

  • Dónde se puede modificar NEW: solo en los BEFORE

Lo que un disparador no puede hacer

  • No acepta parámetros. No hay quien se los pase, porque no lo llama nadie: toda la información que recibe le llega por las pseudotablas y por el contexto de la sentencia.
  • No controla la transacción. No puede ejecutar START TRANSACTION, COMMIT ni ROLLBACK.
  • No devuelve resultados a quien lanzó la sentencia: comunica lo que tenga que comunicar escribiendo en tablas o provocando un error que aborte la operación.

La razón de la segunda limitación explica las otras dos: el disparador se ejecuta dentro de la transacción de la sentencia que lo ha provocado, no en una propia. Si pudiera confirmar o deshacer por su cuenta, rompería la atomicidad de esa transacción, que es justo lo que la transacción existe para garantizar. Todo lo que hace el disparador se confirma o se deshace junto con la sentencia que lo disparó.

Esa regla tiene una excepción conocida: las transacciones autónomas de Oracle, que permiten que un bloque se confirme aparte del que lo llamó. Se usan precisamente para dejar constancia en una auditoría aunque la operación principal termine deshaciéndose, y son la respuesta a por qué a veces sobrevive el registro de un cambio que nunca llegó a aplicarse.

Queda un riesgo de diseño que no es una prohibición pero se pregunta igual: un disparador que escribe en una tabla que a su vez tiene disparadores desencadena una cascada. El gestor limita la profundidad del anidamiento, y una recursión mal cerrada acaba en error de ejecución.

Para el examen

  • Lo que no acepta: parámetros

  • Lo que no devuelve: resultados

  • Lo que no puede ejecutar: COMMIT ni ROLLBACK: corre dentro de la transacción que lo dispara

  • Excepción: las transacciones autónomas de Oracle