1. Se ejecutaron una serie de instrucciones y triggers en Oracle SQL Developer para entender cómo se crean y funcionan los triggers. 2. Los triggers permiten ejecutar acciones automáticamente en respuesta a eventos como inserciones, eliminaciones o actualizaciones en tablas. 3. Las pruebas demostraron cómo los triggers pueden agregar datos, validar datos y restringir operaciones.
Actividad integradora 6 CREAR UN RECURSO MULTIMEDIA
Triggers en SQL
1. 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
2. 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 sqldeveloper) 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 triggeres 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 sqldeveloper
dándonos las siguiente tablas:
3. Al ejecutar las pruebas paso lo siguiente:
INSERT INTO deptoVALUES(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 deptoVALUES(1, 'uno', 'paris', 0);
4. 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 deptoVALUES(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);
Yaque el numero „2‟ al final delregistro, no
existeningundepartamento con estenumero, 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.
5. Se crea el trigger siguiente
CREATE TRIGGER t1
BEFORE UPDATE ON employee
FOR EACH ROW
BEGIN
: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 t2
BEFORE INSERT ON employee
FOR EACH ROW
WHEN (new.deptnum IS NOT NULL)
DECLARE x NUMBER;
BEGIN
SELECT count(*) INTO x
FROM 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:
6. 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 t7
AFTER INSERT OR DELETE OR UPDATE OF deptnum ON employee
FOR EACH ROW
DECLARE x NUMBER;
BEGIN
IF ((INSERTING) AND :new.deptnum IS NOT NULL) THEN
SELECT count(*) INTO x
FROM depto WHERE deptnum=:new.deptnum;
IF x = 0 THEN INSERT INTO deptovalues(: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:
7. 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 t3
AFTER UPDATE OF deptnum ON depto
FOR EACH ROW
BEGIN
IF :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 t4
BEFORE DELETE ON depto
FOR EACH ROW
BEGIN
UPDATE employee SET employee.deptnum = NULL
WHERE employee.deptnum = :old.deptnum;
END;
Los resultados del trigger 4 fueron los siguientes:
8. 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 t5
BEFORE INSERT OR DELETE OR UPDATE OF deptnum ON employee
FOR EACH ROW
DECLARE
dummy INTEGER;
emp_present EXCEPTION;
emp_non_present EXCEPTION;
invalid_department EXCEPTION;
valid_departmentEXCEPTION;
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
9. RAISE_APPLICATION_ERROR(-20000,'Numero
departementinvalide '|| 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 t8
BEFORE DELETE OR UPDATE OF deptnum ON depto
FOR EACH ROW
DECLARE
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 estedepartemento :
'|| TO_CHAR(:old.deptnum));
CLOSE dummy_cursor;
WHEN emp_non_present THEN CLOSE dummy_cursor;
END;
Ejecutando las pruebas se ve lo siguiente:
10. Se agrego el departamento no 81, que tiene 1 numero de empleados, al ejecutar la
siguiente instrucción:
deletedepto 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 t9
BEFORE UPDATE OF sal ON employee
FOR EACH ROW
WHEN (new.sal> 5000)
BEGIN
INSERT INTO avert values(employee.empno, employee.sal);
END;
Ejecutando la siguiente línea
update 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.
11. Para el siguiente trigger se creo la siguiente tabla:
Y en trigger siguiente
CREATE TRIGGER t10
BEFORE INSERT OR UPDATE OF sal ON employee
FOR EACH ROW
DECLARE
maxsal NUMBER;
x NUMBER;
salaire_max EXCEPTION;
BEGIN
IF ( (UPDATING) AND :new.job != 'MANAGER') THEN
SELECT sal INTO maxsal FROM dirsal
WHERE deptnum = :old.deptnum;
IF (:new.sal>= maxsal) THEN
RAISE salaire_max;
END IF;
END IF;
IF ((UPDATING OR INSERTING) AND :new.job = 'MANAGER') THEN
UPDATE dirsal SET sal= :new.sal;
END IF;
EXCEPTION
WHEN salaire_max THEN
raise_application_error(-20002,'salario ' ||
TO_CHAR(:new.sal) || 'FF superior al de MANAGER' ||
TO_CHAR(maxsal) || 'FF paraempleado ' || 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.
12. 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 t12
BEFORE INSERT OR DELETE OR UPDATE ON employee
DECLARE
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 ) THEN
RAISE hora_trabajo;
END IF;
EXCEPTION
WHEN weekends THEN
RAISE_APPLICATION_ERROR (-20005,'Modificacion
invalidadurante los fines de semana !');
WHEN heure_travail THEN
RAISE_APPLICATION_ERROR (-20006,'Modification
invalidafuera de lashoras de trabajo !');
END;