De los tres tipos de disparadores, veremos los asociados a tablas.
Por lo visto anteriormente, para definir un disparador deberemos indicar si será lanzado antes o después de la ejecución de la sentencia que lo lanza, si se lanzará una vez por sentencia o una vez por fila a la que afecta, y si será lanzado al insertar y/o al actualizar y/o al borrar.
La sintaxis que seguiremos para definir un disparador será la siguiente:
CREATE [OR REPLACE] TRIGGER nombre
momento acontecimiento ON tabla
[[REFERENCING (old AS alias_old|new AS alias_new)
FOR EACH ROW
[WHEN condicion]]
bloque_PL/SQL;
Donde nombre nos indica el nombre
que le damos al disparador, momento
nos dice cuando será lanzado el disparador (BEFORE
o AFTER
), acontecimiento
será la acción que provoca el lanzamiento del disparador (INSERT
y/o DELETE
y/o UPDATE
). REFERENCING
y WHEN
sólo podrán ser utilizados con disparadores para filas. REFERENCING
nos permite asignar un alias a los valores NEW
o/y OLD
de las filas afectadas por la operación, y WHEN
nos permite indicar al disparador que sólo sea lanzado cuando sea TRUE
una cierta condición evaluada para cada fila afectada.
En un disparador de fila, podemos acceder a los valores antiguos y nuevos de la fila afectada por la operación, referenciados como :old
y :new
(de ahí que podamos utilizar la opción REFERENCING
para asignar un alias). Si el disparador es lanzado al insertar, el valor antiguo no tendrá sentido y el valor nuevo será la fila que estamos insertando. Para un disparador lanzado al actualizar el valor antiguo contendrá la fila antes de actualizar y el valor nuevo contendrá la fila que vamos actualizar. Para un disparador lanzado al borrar sólo tendrá sentido el valor antiguo.
En el cuerpo de un disparador también podemos acceder a unos predicados que nos dicen qué tipo de operación se está llevando a cabo, que son: INSERTING
, UPDATING
y DELETING
.
Un disparador de fila no puede acceder a la tabla asociada. Se dice que esa tabla está mutando. Si un disparador es lanzado en cascada por otro disparador, éste no podrá acceder a ninguna de las tablas asociadas, y así recursivamente.
CREATE TRIGGER prueba BEFORE UPDATE ON agentes
FOR EACH ROW
BEGIN
...
SELECT identificador FROM agentes WHERE ...
/*devolvería el error ORA-04091: table AGENTES is mutating, trigger/function may not see it*/
...
END;
/
Si tenemos varios tipos de disparadores sobre una misma tabla, el orden de ejecución será:
- Triggers before de sentencia.
- Triggers before de fila.
- Triggers after de fila.
- Triggers after de sentencia.
Existe una vista del diccionario de datos con información sobre los disparadores: USER_TRIGGERS
;
SQL>DESC USER_TRIGGERS;
Name Null? Type
------------------------------- -------- ----
TRIGGER_NAME NOT NULL VARCHAR2(30)
TRIGGER_TYPE VARCHAR2(16)
TRIGGERING_EVENT VARCHAR2(26)
TABLE_OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
REFERENCING_NAMES VARCHAR2(87)
WHEN_CLAUSE VARCHAR2(4000)
STATUS VARCHAR2(8)
DESCRIPTION VARCHAR2(4000)
TRIGGER_BODY LONG