You are on page 1of 18

Disparadores

Un disparador (o trigger) es un tipo especial de procedimiento almacenado asociado a una tabla que se ejecuta al realizar una operacin bsica (INSERT, un DELETE o un UPDATE) sobre sta. La operacin bsica que despierta al trigger es conocida como sentencia disparadora. La ejecucin del disparador puede ser antes (before) o despus (after) de llevar a cabo la sentencia disparadora. Es posible especificar condiciones adicionales para la ejecucin del disparador (restrictores). Dado que una sentencia disparadora puede afectar una o ms filas de una tabla, es necesario especificar si se quiere que el disparador se ejecute para cada una de las filas afectadas o para el bloque en general. Para disear un disparador hay que cumplir dos requisitos: Especificar las condiciones en las que se va a ejecutar el disparador. Esto se descompone en un evento que causa la comprobacin del disparador y una condicin que se debe cumplir para ejecutar el disparador. Especificar las acciones que se van a realizar cuando se ejecute el disparador. Los triggers PL/SQL constituyen una potente herramienta para mantener la integridad de la base de datos, ya que

pueden llevar a cabo cualquier accin que sea necesaria para el mantenimiento de dicha integridad. Los triggers PL/SQL pueden llamar a otros procedimientos y disparar otros triggers, pero no admiten parmetros y no pueden ser invocados desde otros procedimientos PL/SQL. La sintaxis de un disparador Oracle es CREATE [OR REPLACE] TRIGGER nombre {BEFORE | AFTER | INSTEAD OF} // Temporalidad del Evento {INSERT | DELETE | UPDATE [OF <lista de columnas>]} ON <tabla> [FOR EACH ROW | STATEMENT] //Granularidad [WHEN condicin] [DECLARE//Declaracin de variables ] BEGIN cuerpo del trigger [EXCEPTION ] END; Suponga que se tienen las siguientes relaciones, asociadas a la concesin de prstamos en un banco:

Para implementar el diagrama entidad relacin se tiene en Oracle el siguiente cdigo CREATE TABLE DEUDOR ( IFE CHAR(13) NOT NULL, NOMBRE CHAR(50) NOT NULL, DIRECCION CHAR(100) NOT NULL, TELEFONO CHAR(10) NOT NULL, CONSTRAINT PKDeudor PRIMARY KEY (NDeudor); ); CREATE TABLE PRESTAMO ( NPRESTAMO NUMBER(5) NOT NULL PRIMARY KEY, IFE CHAR(13) UNIQUE REFERENCES Deudor(IFE), INTERES NUMBER(4,2) NOT NULL, MONTO NUMBER(8) NOT NULL CHECK(monto > 0) ); CREATE TABLE PAGO ( NPRESTAMO NUMBER(5) NOT NULL, NPAGO NUMBER(2) NOT NULL,

CANTIDAD NUMBER(8) CHECK (CANTIDAD >0), F_VENC DATE NOT NULL, F_PAGO DATE, CONSTRAINT PKCUOTA PRIMARY KEY (NCUOTA), CONSTRAINT FKCUOTA_PRESTAMO FOREIGN KEY (NPRESTAMO) REFERENCESPRESTAMO(NPRESTAM O) );

En la creacin de las tablas se incluyeron todas las restricciones, excepto aquella que dice que toda cuota debe ser pagada antes de su fecha de vencimiento. A continuacin se presenta el diseo del disparador que garantiza el cumplimiento de esta restriccin: Sentencia Disparadora: Como en la BD estn todas los pagos (realizados o no) asociadas a los prstamos, la fecha de pago se actualiza. Por lo tanto, la sentencia disparadora es la actualizacin de fecha de pago en la tabla Pagos. Antes / Despus: La restriccin de integridad no se puede violar, por lo tanto el trigger debe ser disparado antes de realizar la actualizacin. Para Todas/Para el bloque: La verificacin de la restriccin se hace para todas las filas que se actualicen al ejecutar la sentencia disparadora. Restrictor: Se debe impedir la actualizacin, slo cuando la fecha de pago sea mayor que la fecha de vencimiento de la cuota. Accin: Dar un error por violacin de la restriccin.

A continuacin se especifica el trigger asociado con la tabla Pago: CREATE OR REPLACE TRIGGER DIS_PAGO BEFORE UPDATE OF f_pago ON Pago FOR EACH ROW WHEN (new.f_pago > old.f_venc) BEGIN raise_application_error(-20000, 'Pago ' || TO_CHAR(:old.nPago) || ' del prestamo ' ||TO_CHAR(:old.nPrestamo) || ' vencida. Por favor, dirigirse a la gerencia.'); END;

Los disparadores sea activan al crearlos. Eliminar un disparador: DROP TRIGGER nombre_disparador; Activar/ Desactivar dispadores: Existen dos opciones. ALTER TRIGGER nombre_disparador {DISABLE | ENABLE}; ALTER TABLE nombre_tabla {ENABLE | DISABLE} ALL TRIGGERS; Temporalidad del Evento: AFTER / BEFORE BEFORE: Ejecutan la accin asociada antes de que la sentencia sea ejecutada Decidir si la accin debe realizarse o no Utilizar valores alternativos para la sentencia

CREATE TRIGGER NombreTrigger BEFORE Insert ON NombreTabla .

AFTER: Ejecutan la accin asociada despus de que se haya ejecutado la sentencia CREATE TRIGGER NombreTrigger AFTER Insert ON NombreTabla . INSTEAD OF: Desde Oracle 8 se proporciona los disparadores de sustitucin, con ciertas restricciones INSTEAD OF es una clusula vlida solo para vistas; no se puede especificar un disparador INSTEAD OF en una tabla. Si una vista tiene un disparador INSTEAD OF, cualquier vista creada sobre sta debe tener a su vez un disparadorINSTEAD OF. Cuando definimos disparadores INSTEAD OF para columnas LOB, podemos leer tanto el seudoregistro :OLD como el seudo-registro :NEW, pero no se puede modificar sus valores. Evento: Tipo de orden DML sobre una tabla que provoca la activacin del disparador.

{INSERT | DELETE | UPDATE [OF <lista de columnas>]} La lista de columnas slo tiene sentido en el evento UPDATE. Granuralidad del Evento: A NIVEL DE FILA: FOR EACH ROW:Ejecutan la accin asociada tantas veces como filas se vean afectadas por la sentencia que lo dispara. Si ninguna fila se ve afectada, no se dispara A NIVEL DE SENTENCIA: FOR EACK STATEMENT: Disparadores con nivel de orden. Es la opcin por defecto. Ejecutan una nica vez la accin asociada, independientemente del nmero de filas que se vean afectadas por la sentencia (incluso si no hay filas afectadas). Condicin: WHEN La clusula WHEN slo es vlida para los disparadores con nivel de fila, no puede contener subconsultas, vistas. Si est presente, el cuerpo del disparador slo se ejecutar para las filas que cumplan la condicin especificada en la clusula. La clusula WHEN tiene la forma: WHEN condicin donde condicin es una expresin booleana que ser evaluada para cada fila. Se puede hacer tambin

referencia a los registros :new y :old dentro de la condicin, pero en ese caso no se utilizan los dos puntos. Registros :old y :new Estas variables se utilizan del mismo modo que cualquier otra variable PL/SQL, con la salvedad de que no es necesario declararlas, son de tipo %ROWTYPE y contienen una copia del registro antes (OLD) y despues(NEW) de la accin SQL (INSERT, UPDATE, DELETE) que ha ejecutado el trigger. Utilizando esta variable podemos acceder a los datos que se estn insertando, actualizando o borrando.

De uso exclusivo en los disparadores de nivel de fila, si se intenta hacer referencia a cualquiera de los dos dentro de otro tipo de disparador, se obtendr un error de compilacin. :old y :new son registros que nos permiten acceder a los datos de la fila actual La siguiente tabla resume los valores regresados por estos seudoregistros en diferentes eventos Evento INSERT NULL Valores DELETE almacenados Seudoregistros :OLD :NEW Nuevos valores NULL

Valores UPDATE almacenados

Nuevos valores

Bloque PL/SQL Bloque es la unidad de estructura bsica en los programas PL/SQL. Supone una mejora en el rendimiento, pues se envan los bloques completos al servidor para ser procesados en lugar de enviar cada secuencia SQL. Partes de un bloque:

Zona de declaraciones: zona opcional. Se declaran los objetos locales (variables, constantes...). Zona de instrucciones: zona obligatoria. Zona de tratamiento de excepciones: zona opcional. Se tratan excepciones en el programa.

Forma de crear un bloque: Zona de declaraciones: DECLARE Tipos de datos NUMBER CHAR (longitud fija) VARCHAR (longitud variable) DATE BOOLEAN (es un tipo PL/SQL, no de

BD). Declaracin implcita del tipo de datos. var1 var2%TYPE var tabla.campo%TYPE Declaracin de registros var tabla%ROWTYPE var cursor%ROWTYPE

Cuerpo: bloque PL/SQL y SQL, este bloque de instrucciones se realiza si se ejecuta la sentencia activadora especificada para el trigger y, si existe una clusula WHEN sta es TRUE. Con las siguientes restricciones:

Un disparador no puede emitir ninguna orden de control de transacciones (COMMIT, ROLLBACK o SAVEPOINT). El disparador se activa como parte de la ejecucin de la orden que provoc el disparo, y forma parte de la misma transaccin que dicha orden. Cuando la orden que provoca el disparo es confirmada o cancelada, se confirma o cancela tambin el trabajo realizado por el disparador. Ningn procedimiento o funcin llamada por el disparador puede emitir rdenes de control de transacciones. No puede contener ninguna declaracin de variables LONG o LONG RAW.

Restricciones en tablas a las que se puede acceder (Tablas Mutantes). No puede modificar las columnas de clave primaria.

INSERTING, DELETING Y UPDATING Si un trigger puede ser activado por ms de un tipo de operacin (por ejemplo, "INSERT OR DELETE OR UPDATE OF Tabla"), el cuerpo del trigger puede utilizar los predicados condicionales INSERTING, DELETING y UPDATINGpara ejecutar bloques especficos de cdigo, dependiendo del tipo de operacin que activ el disparador. La sintaxis es la siguiente CREATE OR REPLACE TRIGGER Ejemplo BEFORE INSERT OR UPDATE OR DELETE ON tabla BEGIN IF DELETING THEN Acciones asociadas al borrado ELSIF INSERTING THEN Acciones asociadas a la insercin ELSIF UPDATING Acciones asociadas a la modificacin END IF; END Ejemplo; En un UPDATE, se puede especificar el nombre de una columna en un predicado condicional UPDATING para

determinar si la columna especificada ha sido actualizada. Por ejemplo: CREATE OR REPLACE TRIGGER Ejemplo BEFORE INSERT OR DELETE OR UPDATE ON tabla BEGIN IF DELETING THEN Acciones asociadas al borrado ELSIF INSERTING THEN Acciones asociadas a la insercin ELSIF UPDATING(COL1) Acciones asociadas a la modificacin ELSIF UPDATING(COL2) Acciones asociadas a la modificacin END IF;

RAISE_APPLICATION_ERROR Permite que un programa PL/SQL pueda generar errores tal y como lo hace Oracle.

Cuando se produce un error no tratado en la seccin EXCEPTION, el error pasa fuera del bloque, al entorno que realiz la llamada. Con RAISE_APPLICATION_ERROR se pueden generar errores similares con el mensaje que se quiera y, como ocurre con los errores generados por Oracle, el programa genera una EXCEPCIN. La excepcin puede tratarse en la seccin EXCEPTION del bloque PL/SQL que

la genera o del bloque que efecte su llamada, usando el manejador OTHERS y SQLCODE/SQLERRM. Formato: RAISE_APPLICATION_ERROR(<NE >, <ME>, [<PE>]) o <NE>: Nmero del error, comprendido entre 20.000 y 20.999. o <ME>: Mensaje del error, de longitud mxima 512 caracteres. o <PE>: Preservar errores es un valor lgico opcional. Indica si el error se introduce a la lista de errores ya generados (TRUE) o sustituye la lista actual con el nuevo error (FALSE, valor predeterminado). Permite generar errores con mensajes ms significativos que los que generara Oracle: Puede utilizarse en la seccin EXCEPTION. Hace que requieran el mismo tratamiento los errores definidos por el usuario y los errores predefinidos.

Hay Excepciones Predefinidas que controlan errores particulares (excepto OTHERS - Todas aquellas excepciones que no son controladas por el sistema manejador excepciones Oracle y/o por las excepciones definidas por el programador, controlando cualquier tipo de error). Algunas son:

INVALID_CURSOR: Se genera al intentar efectuar una operacin ilegal sobre un cursor, como cerrar o intentar extraer datos de un cursor no abierto. CURSOR_ALREADY_OPEN: Surge al intentar abrir un cursor ya abierto. NO_DATA_FOUND: Cuando una orden SELECT..INTO no devuelve ninguna fila o cuando se intenta referenciar un elemento de una tabla PL/SQL al que no se le ha asignado ningn valor previamente. TOO_MANY_ROWS: Si una orden SELECT..INTO devuelve ms de una fila. INVALID_NUMBER: Si falla la conversin de cierto valor a un tipo NUMBER o cuando usamos un dato no numrico en lugar de un dato numrico. VALUE_ERROR: Se genera cada vez que se produce un error aritmtico, de conversin, de truncamiento o de restricciones en una orden procedimental (si es una orden SQL se produce la excepcin INVALID_NUMBER). Ej.: Si asignamos una cadena o nmero de mayor longitud que el tipo de la variable receptora. STORAGE_ERROR y PROGRAM_ERROR: Son errores internos que no deberan producirse. Ocurren respectivamente si PL/SQL se queda sin memoria o por un fallo en el motor PL/SQL de Oracle y debera avisarse del error al departamento de soporte tcnico de Oracle.

DUP_VAL_ON_INDEX: Es el error ORA-1, generado cuando se intenta insertar una fila en una tabla con un atributo UNIQUE y el valor de ese campo en la fila que se intenta insertar ya existe. ZERO_DIVIDE: Intento de divisin por cero.

Ejemplos: Se desea mantener la informacin de los socios del videoClub Patito, aunque estos se den de baja, para lo que se crea una tabla SOCIO_BAJA, que contiene los datos de socio y la fecha de baja y que se actualizar cada vez que se borre un socio. Considere el siguiente cdigo: SOCIO_BAJA CREATE TABLE SOCIO_BAJA ( IFE CHAR(13) NOT NULL, nombreSocio CHAR(40) NOT NULL, direccion CHAR(50) NOT NULL, telefono CHAR(13) NOT NULL, FECHA_BAJA DATE; CONSTRAINT PK_SOCIOBAJA PRIMARY KEY (IFE) ); Disparador CREATE OR REPLACE TRIGGER DIS_SOCIO AFTER DELETE ON SOCIO FOR EACH ROW BEGIN INSERT

INTO Socio_Baja VALUES (:OLD.IFE, :OLD.nombreSocio, :OLD.direccion,:OLD.telefono, SYSDATE); END;

De la tabla empleado considere que el mximo salario posible es de $30,000 y el mnimo de $3,000 mensuales. Cualquier valor fuera de este rango debera ajustarse a esos limites. EMPLEADO CREATE TABLE EMPLEADO( IDEMPLEADO NUMBER(3) NOT NULL, RFC CHAR(14), NOMBREEMPLEADO CHAR(40) NOT NULL, OFICIO CHAR(11) NOT NULL, CARGO CHAR(9) NOT NULL, JEFE NUMBER(3), INGRESO DATE NOT NULL, SALARIO NUMBER(10,2), COMISION NUMBER(10,2), IDDEPARTAMENTO NUMBER(3) NOT NULL, CONSTRAINT DOM_EMPLEADO_SALARIO CHECK ( salario > 0 ), CONSTRAINT PK_EMPLEADO PRIMARY KEY (idEmpleado), CONSTRAINT AK_EMPLEADO UNIQUE (rfc), CONSTRAINT FK_EMPLEADO_JEFE FOREIGN KEY (jefe) REFERENCES Empleado, CONSTRAINT FK_EMPLEADO FOREIGN KEY (idDepartamento) REFERENCES Departamento, CONSTRAINT DOM_EMPLEADO_NOMBREEMPLEADO CHECK

(nombreEmpleado = NLS_UPPER(nombreEmpleado)) ); DISPARADOR CREATE OR REPLACE TRIGGER DIS_EMPLEADO BEFORE INSERT OR UPDATE ON EMPLEADO FOR EACH ROW WHEN ((new.salario < 3000) OR (new.salario > 30000)) BEGIN IF (:new.salario < 3000) THEN UPDATE empleados SET salario = 3000 WHERE idEmpleado = :new.idEmpleado; ELSE (:new.salario > 30000) THEN UPDATE empleados SET salario = 30000 WHERE idEmpleado = :new.idEmpleado; END IF; END;

Compilado Triggers El funcionamiento de un trigger deja de estar ENABLE si dependen de Procedimientos almacenados o funcin en el cuerpo del disparador y este es modificado. Los disparadores DISABLE por razones de dependencia son recompilado en la prxima invocacin. Es posible puede examinar las ALL_DEPENDENCIES para ver las dependencias de un disparador. Por ejemplo, la siguiente declaracin

SELECT NAME, REFERENCED_OWNER, REFERENCED_NAME, REFERENCED_TYPEFROM ALL_DEPENDENCIES WHERE OWNER = 'EPACHECO';

Disparadores

You might also like