triggers en sql
DESCRIPTION
Ejercicios e intrucciones de algunos triggers en la base de datos de OracleTRANSCRIPT
UNIVERSIDAD DE LAS AMÉRICAS PUEBLA
“Triggers”
Dr. José Luis Zechinelli Martini
Integrantes
David Águila Valencia ID 141026
Luis Alejandro Lazcano Gonzales ID140384
Edgar Jair Gutiérrez Granados ID 140851
Primavera 2013
Resumen
Se ejecutaron y compilaron una serie de instrucciones junto con los “triggers” o “disparadores” en el programa de bases de datos de Orcacle (Oracle sql developer) con el fin de entender y comprender de qué manera se crean los triggers y distinguir las restricciones que pueden tenerse en una base de datos.
Introducción
El disparador o trigger es una unidad de PL / SQL que se almacena en la base de datos y (si está activado o desactivado), se ejecuta automáticamente en respuesta a un evento especificado.
Los disparadores tienen la siguiente estructura:
TRIGGER nombre_del_trigger triggering_evento [restricción_del_trigger] BEGIN accion_del_trigger; END;
Nombre_del_trigger, debe de ser único, no debe de haber dos disparadores con un mismo nombre, en caso de que lo haya, mandara un mensaje de error diciéndote que el nombre con ese disparador ya fue creado o compilado.
Triggering_evento, aquí ira sobre que base de datos funcionara para activar la siguiente instruccion.
Acción_del_trigger, aquí van las instrucciones de lo que hara nuestro disparador en caso de que la restricción sea o no valida, las acciones van a manipular nuestros datos.
Resultados
Para la practica se ejecutaron las instrucciones de “schema1.sql” en Oracle sql developer dándonos las siguiente tablas:
Al ejecutar las pruebas paso lo siguiente:
INSERT INTO depto VALUES(1, 'uno', 'puebla', 0);
Esto nos da un error debido a que la ciudad de puebla no esta dada por alta previamente, y solo acepta las ciudades de “parís”,”grenoble” y “lyon”
INSERT INTO depto VALUES(1, 'uno', 'paris', 0);
En esta prueba la inserción fue llevada a cabo correctamente debido a que la localización insertada fue “parís” y esta dentro del rango.
INSERT INTO depto VALUES(2, 'uno', 'paris', 0);
Esta inserción no se llevara a cabo debido a que ya existe un departamento con el nombre “uno” y con el nombre de “parís”.
Las siguientes instrucciones se llevaran a cabo correctamente
INSERT INTO employee VALUES(1, 'vargas', 'enseignant', 1000, '11-DEC-98', 'x', 1);
INSERT INTO employee VALUES(2, 'dupont', 'secretaire', 1000, '11-NOV-98', 'x', 1);
A excepción de la siguiente
INSERT INTO employee VALUES(3, 'dupont', 'enseignant', 1000, '11-NOV-98', 'x', 2);
Ya que el numero ‘2’ al final del registro, no existe ningun departamento con este numero, por lo tanto no se insertara
En la siguiente instrucción:
DELETE depto WHERE deptnum = 1;
Se eliminara el departamento con el numero 1, además de que se hará un eliminado de cascada, es decir que cualquier empleado asociado a este departamento también se eliminara.
Se crea el trigger siguiente
CREATE TRIGGER t1BEFORE UPDATE ON employeeFOR EACH ROWBEGIN:new.datemaj := sysdate;END;
Antes de insertar un registro en la tabla de empleados se le agrega la fecha actual para cada registro, en la siguiente instrucción se prueba el trigger:
select * from employee;update EMPLOYEE set job = 'nouvelle' where empnum = 7369;select * from employee;
Aquí se observa la tabla despues de aplicar las instrucciones
Despues de actualizar la tabla, el disparador 1 actualizo la fecha en que se modifico y la instrucción cmabio el trabajo de “Clerk” a “nouvelle”.
Al ejecutar el siguiente trigger t2
CREATE TRIGGER t2BEFORE INSERT ON employeeFOR EACH ROWWHEN (new.deptnum IS NOT NULL)DECLARE x NUMBER;BEGINSELECT count(*) INTO xFROM depto WHERE deptnum=:new.deptnum;IF x = 0 THEN INSERT INTO depto values(:new.deptnum,'????','paris',1);END IF;END;
Lo que hace es que al no existir un departamento crea uno, se puede ver en la siguiente instrucción:
insert into employee values(7938,'martin','ENSEIGe', 7566,'30-JUN-98', ‘KRONOS’, 90);
dando como resultado el siguiente:
Se compila el siguiente trigger
CREATE TRIGGER t7AFTER INSERT OR DELETE OR UPDATE OF deptnum ON employeeFOR EACH ROWDECLARE x NUMBER;BEGINIF ((INSERTING) AND :new.deptnum IS NOT NULL) THEN SELECT count(*) INTO x FROM depto WHERE deptnum=:new.deptnum; IF x = 0 THEN INSERT INTO depto values(:new.deptnum, '????','paris',1); ELSE UPDATE depto SET nemp = nemp +1 WHERE deptnum:new.deptnum; END IF;END IF;IF ((DELETING) AND :old.deptnum IS NOT NULL) THEN UPDATE depto SET nemp = nemp -1 WHERE deptnum = :old.deptnum;END IF;END;
Lo que hace es modificar el numero de la columna “nemp”, se puede ver el resultado en la siguiente imagen:
Se ve que al agregar los dos empleados de las siguientes instrucciones
insert into employee values(7935, 'VARGAS', 'ANALYST', 7566, NULL, 'KRONOS', 40); insert into employee values(7936, 'WALTER', 'ANALYST', 7566, NULL, 'KRONOS', 20);
El siguiente triger ayuda al usuario a modificiar todos los datos de los empleados cuando se modifica el numero del departamento, es decir cambiara el numero del empleado que estaba en ese departamento al mismo numero
CREATE TRIGGER t3AFTER UPDATE OF deptnum ON deptoFOR EACH ROWBEGINIF :old.deptnum != :new.deptnum THEN
UPDATE employee SET employee.deptnum = :new.deptnum WHERE employee.deptnum = :old.deptnum;END IF;END;
Lo que hace el siguiente trigger es que si eliminamos algun departamento, los empleados que tengan el numero de departamento igual, lo hara “null”
CREATE TRIGGER t4BEFORE DELETE ON deptoFOR EACH ROWBEGINUPDATE employee SET employee.deptnum = NULLWHERE employee.deptnum = :old.deptnum;END;
Los resultados del trigger 4 fueron los siguientes:
creación de un nuevo departamento
Creación de un empleado con el departamento “80”
Al eliminar el departamento con el numero 80, se pone en blanco o en null el numero de departamento que ya no existe.
El siguiente trigger
CREATE TRIGGER t5BEFORE INSERT OR DELETE OR UPDATE OF deptnum ON employeeFOR EACH ROWDECLARE dummy INTEGER; emp_present EXCEPTION; emp_non_present EXCEPTION; invalid_department EXCEPTION; valid_department EXCEPTION;
mutating_table EXCEPTION;CURSOR dummy_cursor (dn NUMBER) IS
SELECT deptnum FROM depto WHERE deptnum = dn;BEGIN OPEN dummy_cursor(:new.deptnum); FETCH dummy_cursor INTO dummy; IF dummy_cursor %NOTFOUND THEN RAISE invalid_department; ELSE RAISE valid_department; END IF; EXCEPTION WHEN invalid_department THEN
RAISE_APPLICATION_ERROR(-20000,'Numero departement invalide '|| TO_CHAR(:new.deptnum)); CLOSE dummy_cursor; WHEN valid_department THEN CLOSE dummy_cursor; WHEN mutating_table THEN NULL;END;
Lo que hara es que si ahora se requiere unsertar un empleado, con un numero de departamento, lo que hara es comparar cada numero si existe en la tabla de departamentos, si lo encuentra, se insertara, si no, no se insertara nada.
Lo que hace el trigger 8 es que ningún departamento que se vaya a suprimir tenga personas asociadas. Se declaran unos valores para la comparación del mismo.
CREATE TRIGGER t8BEFORE DELETE OR UPDATE OF deptnum ON deptoFOR EACH ROWDECLARE dummy INTEGER; emp_present EXCEPTION; emp_non_present EXCEPTION;
CURSOR dummy_cursor (dn NUMBER) IS SELECT deptnum FROM employee WHERE deptnum = dn;BEGIN OPEN dummy_cursor(:old.deptnum); FETCH dummy_cursor INTO dummy; IF dummy_cursor %FOUND THEN RAISE emp_present; ELSE RAISE emp_non_present; END IF; EXCEPTION WHEN emp_present THEN RAISE_APPLICATION_ERROR(-20001,'Empleados en este departemento : '|| TO_CHAR(:old.deptnum)); CLOSE dummy_cursor; WHEN emp_non_present THEN CLOSE dummy_cursor;END;
Ejecutando las pruebas se ve lo siguiente:
Se agrego el departamento no 81, que tiene 1 numero de empleados, al ejecutar la siguiente instrucción:
delete depto where deptnum = 81;
nos aparece un mensaje, debido al disparador 8
El siguiente disparador funcionara sobre la tabla empleados, cada ves que se ponga su salario, el salario no debe de ser menor a 5,000
CREATE TRIGGER t9BEFORE UPDATE OF sal ON employeeFOR EACH ROWWHEN (new.sal > 5000)BEGIN
INSERT INTO avert values(employee.empno, employee.sal);END;
Ejecutando la siguiente líneaupdate employee set sal = 6000 where empno = 7936;
Lo modificara correctamente, sin que nos mencione algun mensaje, en caso si hubiera sido este caso:
update employee set sal = 4999 where empno = 7936;
Se activa el disparador y no modifica nada.
Para el siguiente trigger se creo la siguiente tabla:
Y en trigger siguiente
CREATE TRIGGER t10BEFORE INSERT OR UPDATE OF sal ON employeeFOR EACH ROWDECLARE
maxsal NUMBER; x NUMBER;
salaire_max EXCEPTION;BEGIN
IF ( (UPDATING) AND :new.job != 'MANAGER') THENSELECT sal INTO maxsal FROM dirsalWHERE deptnum = :old.deptnum;
IF (:new.sal >= maxsal) THENRAISE salaire_max;
END IF; END IF;
IF ((UPDATING OR INSERTING) AND :new.job = 'MANAGER') THENUPDATE dirsal SET sal = :new.sal;
END IF;EXCEPTION
WHEN salaire_max THENraise_application_error(-20002,'salario ' ||
TO_CHAR(:new.sal) || 'FF superior al de MANAGER' || TO_CHAR(maxsal) || 'FF para empleado ' || TO_CHAR(:new.empnum));END;
Este trigger lo que hace es antes de insertar o actualizar un salario en la tabla de empleados es comparar el salario máximo que tiene cada uno en la tabla DIRSAL, si alguno supera el salario la inserción o actualización no se hace.
update employee set sal = 8000 where empnum = 7900;
Al ejecutar la prueba, no lo actualizara, debido a que el empleado 7900, es un secretario, y el secretario no debe de ganar mas de 7839.
El siguiente trigger lo que hace es que no se puede modificar, insertar, o actualizar información fuera de horas de trabajo y fines de semana, apareciendo una modificación no valida.
CREATE TRIGGER t12BEFORE INSERT OR DELETE OR UPDATE ON employeeDECLARE
weekends EXCEPTION; hora_trabajo EXCEPTION;
heure_travail EXCEPTION;BEGIN
IF( TO_CHAR(SYSDATE,'DY') = 'SAT' OR TO_CHAR(SYSDATE,'DY') = 'SUN' ) THEN
RAISE weekends;END IF;IF( TO_CHAR(SYSDATE,'HH24') < 12 OR
TO_CHAR(SYSDATE,'HH24') > 13 ) THENRAISE hora_trabajo;
END IF;EXCEPTION
WHEN weekends THENRAISE_APPLICATION_ERROR (-20005,'Modificacion invalida
durante los fines de semana !');WHEN heure_travail THENRAISE_APPLICATION_ERROR (-20006,'Modification invalida
fuera de las horas de trabajo !');END;