Está en la página 1de 20

ASERCIONES Y DISPARADORES

En SQL, podemos especificar restricciones generales (las que no encajan en


ninguna de las categorías descritas como restricciones básicas) mediante
aserciones declarativas, utilizando la sentencia CREATE ASSERTION del
DDL. A cada aserción se le asigna un nombre de restricción y se especifica a través
de una condición parecida a la cláusula WHERE de una consulta SQL. Por
ejemplo, para especificar en SQL la restricción de que el sueldo de un empleado no
debe ser superior al del director del departamento para el que trabaja ese empleado,
podemos escribir la siguiente aserción:

CREATE ASSERTION RESTR_SUELDO


CHECK (NOT EXISTS (SELECT *
FROM EMPLEADO E. EMPLEADO M,
DEPARTAMENTO D
WHERE E.Sueldo > M.Sueldo
AND E.Dno = D.NumeroDpto
AND D.DniDirector = M.Dni ));
ASERCIONES Y DISPARADORES
El nombre de restricción RESTR_SUELDO va seguido por la palabra clave
CHECK, que a su vez va seguida por una condición entre paréntesis que debe ser
verdadera en cada estado de la base de datos para que la aserción sea satisfecha. El
nombre de la restricción se puede utilizar más tarde para referirse a dicha
restricción o para modificarla o eliminarla. El DBMS es responsable de garantizar
que no se viole la condición. Se puede utilizar la condición de cualquier cláusula
WHERE, pero pueden especificarse muchas restricciones utilizando el estilo
EXISTS y NOT EXISTS de las condiciones SQL. En cuanto algunas tuplas de la
base de datos provocan que la condición de una sentencia ASSERTION se evalúe
como FALSE, la restricción es violada. Por otro lado, la restricción es satisfecha
por un estado de la base de datos si ninguna combinación de tuplas de dicho estado
viola la restricción.
La técnica básica para escribir estas aserciones consiste en especificar una consulta
que seleccione las tuplas que violan la condición deseada. Al incluir esta consulta
dentro de una cláusula NOT EXISTS, la aserción especificará que el resultado de
esta consulta debe estar vacío. De este modo, la aserción es violada si el resultado
de la consulta no está vacio. En nuestro ejemplo, la consulta selecciona todos los
empleados cuyo sueldo es mayor que el sueldo del director de su departamento. Si
el resultado de la consulta no está vacío, la aserción es violada.
ASERCIONES Y DISPARADORES
La cláusula CHECK y la condición de la restricción también se pueden utilizar para
especificar restricciones en los atributos, dominios y en las tuplas. Una diferencia
más importante entre CREATE ASSERTION y las otras es que las cláusulas
CHECK en los atributos, los dominios y las tuplas se comprueban en SQL sólo
cuando se insertan o actualizan las tuplas. Por tanto, la comprobación de la
restricción se puede implementar de forma más eficaz por parte de los DBMSs en
estos casos. El diseñador del esquema debe utilizar CHECK en los atributos, los
dominios y las tuplas sólo cuando está seguro de que la restricción sólo puede ser
violada por la inserción o la actualización de tuplas.
Por el contrario, el diseñador del esquema debe usar CREATE ASSERTION sólo
en los casos en que no es posible utilizar CHECK en los atributos, los dominios o
las tuplas, para que el DBMS pueda realizar las comprobaciones con más eficacia.
Otra sentencia relacionada con CREATE ASSERTION es CREATE TRIGGER,
pero los triggers se utilizan de modo diferente. En muchos casos es conveniente
especificar el tipo de acción que se llevará a cabo cuando se producen ciertos
eventos y cuando se satisfacen determinadas condiciones. En lugar de ofrecer al
usuario la opción de abortar una operación que provoca una violación (como con
CREATE ASSERTION) el DBMS debe contar con otras opciones. Por ejemplo,
puede ser útil especificar una condición que, en caso de ser violada, informe al
usuario de alguna forma, por ejemplo, enviando un mensaje al usuario.
ASERCIONES Y DISPARADORES
La acción que el DBMS debe tomar en este caso es enviar un mensaje a ese
usuario. La condición se utiliza entonces para monitorizar la base de datos. Es
posible especificar otras acciones, como la ejecución de un procedimiento
almacenado específico o la activación de otras actualizaciones. En SQL se utiliza la
sentencia CREATE TRIGGER para implementar dichas acciones. Un trigger
especifica un evento (por ejemplo, una operación de actualización de la base de
datos), una condición y una acción. La acción se ejecuta automáticamente si se
satisface la condición cuando se produce el evento.
CONCEPTOS DE BASES DE DATOS ACTIVAS Y TRIGGER

Durante algún tiempo, se han considerado mejoras importantes de los sistemas de


bases de datos las reglas que especifican acciones que se activan automáticamente a
causa de ciertos eventos. De hecho, el concepto de triggers (una técnica para
especificar determinados tipos de reglas activas) existía en versiones anteriores de
la especificación SQL para las bases de datos relacionales, y los triggers forman
ahora parte del estándar SQL-99. Los DBMSs relacionales comerciales (como
Oracle, DB2 y SYBASE) tienen disponibles determinadas versiones de triggers.
Sin embargo, parece haberse investigado mucho respecto al modelo general para
las bases de datos activas desde que se propusieran los primeros modelos de
triggers.
ASERCIONES Y DISPARADORES
Presentaremos los conceptos generales que se han propuesto para especificar reglas
para las bases de datos activas. Utilizaremos la sintaxis del DBMS relacional
comercial Oracle para ilustrar estos conceptos con ejemplos específicos, ya que los
triggers de Oracle se acercan a cómo se especifican las reglas en el estándar SQL
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

El modelo que se ha utilizado para especificar las reglas de las bases de datos
activas se conoce como evento-condición-acción, o modelo ECA. Una regla en el
modelo ECA tiene tres componentes:
El (los) evento(s) que provoca(n) la acción: normalmente, estos eventos son las
operaciones de modificación de la base de datos que se aplican explícitamente a la
misma. No obstante, en el modelo general, podrían ser también eventos temporales
(especificado como una hora periódica: por ejemplo activar esta regla cada día a
las 5:30 A.M.) u otros tipos de eventos externos.
La condición que determina si debe ejecutarse la acción de la regla: una vez que se
ha producido el evento de activación, puede evaluarse una condición opcional. Si
no se especifica una condición, la acción se ejecutará una vez que se produce el
evento. Si se especifica una condición, primero se evalúa ésta y, sólo si es
verdadera, se ejecutará la acción de la regla.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

acción que se tomará: la acción es normalmente una secuencia de sentencias SQL,


pero también puede ser una transacción de base de datos o un programa externo
que se ejecutará automáticamente.
A fin de ilustrar estos conceptos, vamos a considerar algunos ejemplos. Los
ejemplos están basados en una variante muy simplificada de la base de datos
EMPRESA (Figura 1) según la cual cada empleado tiene un nombre (Nombre), un
número de documento nacional de identidad (Dni), un salario (Sueldo), el
departamento al que está actualmente asignado (Dno, una clave externa a
DEPARTAMENTO) y un supervisor directo (SuperDni, una clave externa
[recursiva] a EMPLEADO). Para este ejemplo, asumimos que para Dno está
permitido el valor NULL, lo que representaría un empleado que actualmente no
está asignado a ningún departamento. Cada departamento tiene un nombre
(NombreDpto), un número (Dno), el salario total de todos los empleados asignados
al departamento (SueldoTotal) y un director (DniDirector, una clave externa a
EMPLEADO).
El mantenimiento del valor correcto del atributo derivado SueldoTotal se puede
lograr mediante una regla activa.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Primero tenemos que determinar los eventos que pueden causar un cambio en el
valor de SueldoTotal, que son los siguientes:

1. Inserción (uno o más) de nuevas tuplas de empleado.


2. Modificación del sueldo de los empleados existentes (uno o más).
3. Modificación de la asignación de los empleados existentes de un departamento
a otro.
4. Eliminación de tuplas de empleado (una o más).
Figura 1. Una base de datos EMPRESA simplificada que utilizaremos para los
ejemplos de reglas.
EMPLEADO (Nombre, Dni, Sueldo, Dno, SuperDni)
DEPARTAMENTO (NombreDpto, Dno, SueldoTotal, DniDirector
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

En el caso del evento 1, sólo tenemos que recalcular SueldoTotal si el empleado


nuevo es asignado inmediatamente a un departamento; es decir, si el valor del
atributo Dno para el empleado nuevo no es NULL (asumiendo que para Dno
permitimos NULL). Por tanto, ésta sería la condición que tendríamos que
comprobar.
Para el evento 2 (y 4) podríamos evaluar una condición parecida, a fin de
determinar si el empleado cuyo sueldo ha cambiado (o empleado que hemos
eliminado) está actualmente asignado a un departamento. En el caso del evento 3,
siempre tenemos que ejecutar una acción para mantener el valor correcto de
SueldoTotal, por lo que no necesitamos condición alguna (la acción siempre se
ejecuta).
La acción para los eventos 1, 2 y 4 es para actualizar automáticamente el valor de
SueldoTotal para el departamento del empleado, a fin de reflejar el sueldo del
empleado recién insertado, actualizado o eliminado. En caso del evento 3,
necesitamos una acción doble; una para actualizar el SueldoTotal del departamento
antiguo del empleado y otra para actualizar el SueldoTotal del departamento nuevo
del empleado.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Las cuatro reglas activas (o triggers) R1, R2, R3 y R4 (correspondientes a la


situación anterior) se pueden especificar con la notación del DBMS Oracle como se
muestra en la Figura 2(a). Vamos a considerar la regla R1 para ilustrar la sintaxis
de creación de triggers en Oracle.
La sentencia CREATE TRIGGER especifica un nombre de trigger (o regla activa):
SueldoTotal1 para R1. La cláusula AFTER especifica que la regla se activará
después de que se produzcan los eventos que activan la regla. Los eventos de
activación (la inserción de un empleado nuevo en este ejemplo) se especifican a
continuación de la palabra clave AFTER. Otra opción es poder especificar
BEFORE, que indica que la regla se activa antes de que se ejecute el evento de
activación.
La cláusula ON especifica la relación en la que la regla está especificada:
EMPLEADO para R1. Las palabras clave opcionales FOR EACH ROW
especifican que la regla se activará una vez por cada fila que se vea afectada por el
evento de activación. En los triggers a nivel de sentencia, la regla se activa una sola
vez aun cuando varias filas (tuplas) se vean afectadas por el evento de activación
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

La cláusula opcional WHEN se utiliza para especificar las condiciones que sea
preciso evaluar después de haberse activado la regla, pero antes de que la acción se
ejecute. Por último, la o las acciones que deban tomarse se especifican como un
bloque PL/SQL, que normalmente contiene una o más sentencias SQL o llamadas
para ejecutar procedimientos externos.
Figura 2. Especificación de reglas activas como triggers en la notación de Oracle.
(a) Triggers para el mantenimiento automático de la coherencia de SueldoTotal de
DEPARTAMENTO. (b) Trigger para comparar el sueldo de un empleado con el de
su supervisor.
a. R1: CREATE TRIGGER SueldoTotal1
AFTER INSERT ON EMPLEADO
FOR EACH ROW
WHEN ( NEW.Dno IS NOT NULL )
. UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal + NEW.Sueldo
WHERE Dno = NEW.Dno;
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y LOS
TRIGGERS DE ORACLE

R2: CREATE TRIGGER SueldoTotal2


AFTER UPDATE OF Sueldo ON EMPLEADO
FOR EACH ROW
WHEN ( NEW.Dno IS NOT NULL )
UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal + NEW.Sueldo - OLD.Sueldo
WHERE Dno = NEW.Dno;
R3: CREATE TRIGGER SueldoTotal3
AFTER UPDATE OF Dno ON EMPLEADO
FOR EACH ROW
BEGIN
UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal + NEW.Sueldo
WHERE Dno = NEW.Dno;
UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal - OLD.Sueldo
WHERE Dno = OLD.Dno;
END;
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

R4: CREATE TRIGGER SueldoTotal4


AFTER DELETE ON EMPLEADO
FOR EACH ROW
WHEN ( OLD.Dno IS NOT NULL )
UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal - OLD.Sueldo
WHERE Dno = OLD.Dno;

b. R5: CREATE TRIGGER Inform_supervisor1


BEFORE INSERT OR UPDATE OF Sueldo, SuperDni
ON EMPLEADO
FOR EACH ROW
WHEN ( NEW.Sueldo > ( SELECT Sueldo FROM EMPLEADO
WHERE Dni = NEW.SuperDni ))
inform_supervisor(NEW.SuperDni, NEW.Dni );
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Los cuatro triggers (reglas activas) R1, R2, R3 y R4 ilustran varias características
de las reglas activas. En primer lugar, los eventos básicos que pueden especificarse
para activar las reglas son comandos de actualización SQL estándar: insertar,
eliminar y actualizar, que se especifican mediante las palabras clave INSERT,
DELETE y UPDATE en la notación de Oracle. En este caso de actualización
(UPDATE) podemos especificar los atributos que van a actualizarse: por ejemplo,
escribiendo UPDATE OF Sueldo, Dno. En segundo lugar, el diseñador de la regla
debe poder referirse a las tuplas que el evento de activación ha insertado, eliminado
o modificado. En la notación de Oracle también se utilizan las palabras clave NEW
y OLD; NEW se utiliza para hacer referencia a una tupla recién insertada o
actualizada, mientras que OLD se utiliza para hacer referencia a una tupla
eliminada o a una tupla antes de ser actualizada.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Por tanto, la regla R1 se activa después de haberse aplicado una operación INSERT
a la relación EMPLEADO. En R1 se comprueba la condición (NEW.Dno IS NOT
NULL), y si se evalúa como verdadera, significa que el empleado recién insertado
está relacionado con un departamento, por lo que se ejecuta la acción. La acción
actualiza la tupla o tuplas DEPARTAMENTO relacionadas con el empleado recién
insertado añadiendo su sueldo (NEW.Sueldo) al atributo SueldoTotal de su
departamento relacionado.
La regla R2 es parecida a la R1, pero es activada por una operación UPDATE que
actualiza el SUELDO de un empleado, y no por una operación INSERT. La regla
R3 es activada por una actualización del atributo Dno de EMPLEADO, que
significa cambiar la asignación de un empleado de un departamento a otro. En R3
no hay una condición, por lo que la acción se ejecuta siempre que se produce el
evento de activación. La acción actualiza tanto el departamento antiguo como el
nuevo de los empleados reasignados, añadiendo su sueldo al SueldoTotal de su
nuevo departamento y sustrayendo su sueldo del SueldoTotal de su departamento
antiguo.
Esto debe funcionar aun en el caso de que el valor de Dno fuera NULL, porque en
este caso ningún departamento se seleccionará para la acción de la regla.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Es importante observar el efecto de la cláusula FOR EACH ROW opcional, que


significa que la regla se activa separadamente para cada tupla. Es lo que se conoce
como trigger a nivel de fila. Si omitimos esta cláusula, el trigger se denominaría
trigger a nivel de sentencia y se activaría una vez por cada sentencia de
activación. Para ver la diferencia, consideremos la siguiente operación de
actualización, que aumenta un 10% el sueldo de todos los empleados asignados al
departamento 5. Esta operación sería un evento que activaría la regla R2:
UPDATE EMPLEADO
SET Sueldo = 1.1 * Sueldo
WHERE Dno = 5:
Como la sentencia anterior podría actualizar varios registros, se activaría una regla
que utiliza la semántica a nivel de fila, como R2 en la Figura 2, por cada fila,
mientras que una regla que utiliza la semántica a nivel de sentencia sólo se activaría
una vez. El sistema Oracle permite elegir cuál de las opciones anteriores vamos a
utilizar para cada regla. Las palabras clave NEW y OLD sólo se pueden utilizar con
triggers a nivel de fila.
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE

Como segundo ejemplo, supongamos que queremos comprobar si el sueldo de un


empleado es mayor que el de su supervisor(a) directo(a). Varios eventos pueden
activar esta regla: la inserción de un empleado nuevo, la modificación del sueldo de
un empleado, o la modificación del supervisor de un empleado. Suponga que la
acción a tomar fuera llamar a un procedimiento externo inform_supervisor, que
notificará al supervisor, la regla podría escribirse como R5 (Figura 2[b]).
ASERCIONES Y DISPARADORES
MODELO GENERALIZADO PARA LAS BASES DE DATOS ACTIVAS Y
LOS TRIGGERS DE ORACLE
La Figura 3 muestra la sintaxis para especificar algunas de las opciones principales
disponibles en los triggers de Oracle. Luego describiremos la sintaxis de los
triggers en el estándar SQL-99.
Figura 3. Resumen de la sintaxis para especificar triggers en el sistema Oracle (sólo
opciones principales)
<trigger> ::= CREATE TRIGGER <nombre del trigger>
( AFTER | BEFORE ) <eventos de activación> ON <nombre
de la tabla>
[ FOR EACH ROW ]
[ WHEN <condición> ]
<acciones del trigger> ;
<eventos de activación> ::= <evento trigger> {OR <evento trigger> }
<evento trigger> ::= INSERT | DELETE | UPDATE [ OF <nombre
columna> {,
<nombre columna> } ]
<acción trigger> ::= <bloque PL/SQL>
ASERCIONES Y DISPARADORES
TRIGGERS EN SQL-99

Los triggers en el estándar SQL-99 son muy parecidos a los ejemplos que hemos
visto, con algunas diferencias sintácticas menores. Los eventos básicos que
podemos especificar para activar las reglas son los comandos de actualización SQL
estándar: INSERT, DELETE y UPDATE. En el caso de UPDATE, podemos
especificar los atributos que se van a modificar. Están permitidos los triggers a
nivel de fila y a nivel de sentencia, que se indican en el trigger con las cláusulas
FOR EACH ROW y FOR EACH STATEMENT, respectivamente. Una diferencia
sintáctica es que el trigger puede especificar nombres de variable de tupla
particulares para las tuplas antigua y nueva, en lugar de utilizar las palabras clave
NEW y OLD, como mostramos en la Figura 2. El trigger T1 de la Figura 4 muestra
cómo podemos especificar en SQL-99 el trigger a nivel de fila R2 de la Figura 2
(a). Dentro de la cláusula REFERENCING, utilizamos las variables de tupla con
nombre (alias) O y N para referirnos a la tupla OLD (antes de la modificación) y a
la tupla NEW (después de la modificación), respectivamente. El trigger T2 de la
Figura 4 muestra cómo podemos especificar en SQL-99 el trigger de la regla R2 a
nivel de sentencia. En el caso de un trigger a nivel de sentencia, utilizamos la
cláusula REFERENCING para referimos a la tabla de todas las tuplas nuevas
(recién insertadas o modificadas) como N, mientras que a la tabla de todas las
tuplas antiguas (tuplas eliminadas o tuplas antes de que fueran actualizadas) nos
referimos como O.
ASERCIONES Y DISPARADORES
TRIGGERS EN SQL-99

Figura 4. El trigger T1 ilustra la sintaxis para definir triggers en SQL-99.

T1: CREATE TRIGGER SueldoTotal1


AFTER UPDATE OF Sueldo ON EMPLEADO
REFERENCING OLD ROW AS O, NEW ROW AS N
FOR EACH ROW
WHEN ( N.Dno IS NOT NULL )
UPDATE DEPARTAMENTO
SET SueldoTotal = SueldoTotal + N.sueldo - O.sueldo
WHERE Dno = N.Dno;
ASERCIONES Y DISPARADORES
TRIGGERS EN SQL-99

Figura 4.

T2: CREATE TRIGGER SueldoTotal2


AFTER UPDATE OF Sueldo ON EMPLEADO
REFERENCING OLD TABLE AS O, NEW TABLE AS N
FOR EACH STATEMENT
WHEN EXISTS ( SELECT * FROM N WHERE N.Dno IS NOT NULL
) OR
EXISTS ( SELECT * FROM O WHERE O.Dno IS NOT NULL )
UPDATE DEPARTAMENTO AS D
SET D.SueldoTotal = D.SueldoTotal
+ ( SELECT SUM (N.Sueldo) FROM N WHERE D.Dno = N.Dno )
- ( SELECT SUM (O.Sueldo) FROM O WHERE D.Dno = O.Dno )
WHERE D,Dno IN (( SELECT Dno FROM N ) UNION
( SELECT Dno FROM O ));

También podría gustarte