Está en la página 1de 18

Continuacin prctica, a partir del ejercicio 6 incluido: *Conexin a la base de datos:* startup pfile=/home/oracle/oracle/product/10.2.0/db_1/dbs/initasir1.

ora SET SERVEROUTPUT ON SIZE UNLIMITED 19. Como usuario GESTOR, cree una tabla CTRL_PAISES con los mismos atributos que la tabla CTRL_ACTIVIDADES, y programe un disparador a nivel de orden de tipo BEFORE sobre la tabla de Pases, que se active cuando se borre sobre esa tabla. El disparador insertar en dicha tabla los valores correctos de usuario y fecha y en el atributo OPERACION tomar el valor 'BEFORE DELETE'. Compruebe que el disparador tambin funciona para el usuario AKSEN. Creamos con GESTOR la tabla CTRL_PAISES: CREATE TABLE CTRL_PAISES ( usuario VARCHAR2(25), fecha DATE, operacion VARCHAR2(20)); SQL> conn gestor Enter password: Connected. SQL> @'paises/ctrl_paises.sql'; Table created. SQL> desc ctrl_paises; Name --------USUARIO FECHA OPERACION Null? ---Type ------------VARCHAR2(25) DATE VARCHAR2(20)

Creamos el disparador de tipo BEDORE que inserta una fila en esta tabla cada vez que se borre un dato dentro de la tabla PAISES: CREATE OR REPLACE TRIGGER ejer19 BEFORE DELETE ON gestor.paises FOR EACH ROW DECLARE v_user VARCHAR2(25); BEGIN SELECT USER INTO v_user FROM DUAL; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'BEFORE DELETE'); END ejer19; / SQL> @'paises/ejer19.sql'; Trigger created. Aadimos dos paises de "prueba" para comprobar que el trigger se ejecuta c orrectamente tanto con el usuario GESTOR como con AKSEN. INSERT INTO paises VALUES (5, 'Brasil', 'Brasilia', 625000); INSERT INTO paises VALUES (6, 'Francia', 'Paris', 1200000);

SQL> INSERT INTO paises VALUES (5, 'Brasil', 'Brasilia', 625000) ; 1 row created. SQL> INSERT INTO paises VALUES (6, 'Francia', 'Paris', 1200000); 1 row created. Con el usuario GESTOR borramos el primero de ellos y comprobamos que el trigger se ha ejecutado: SQL> show user USER is "GESTOR" SQL> delete from paises where cod_pais=5; 1 row deleted. SQL> select * from ctrl_paises; USUARIO FECHA OPERACION ------------------------- --------- -------------------GESTOR 07-MAR-12 BEFORE DELETE Lo mismo con el usuario AKSEN sobre el segundo aadido: SQL> conn aksen Enter password: Connected. SQL> delete from gestor.paises where cod_pais=6; 1 row deleted. SQL> select * from ctrl_paises; USUARIO ------------------------GESTOR AKSEN FECHA --------07-MAR-12 07-MAR-12 OPERACION -------------------BEFORE DELETE BEFORE DELETE

Por su puesto, como el usuario AKSEN no tiene ningn permiso sobre la tabla ctrl_paises, para comprobar que el trigger se ha ejecutado correctamente he tenido que volver a conectarme con el usuario GESTOR, y se puede ver como se han borrado los dos paises aadidos previamente cada uno con un usuario.

20. De manera similar al ejercicio anterior, cree un disparador a nivel de orden de tipo AFTER sobre la tabla de Pases, que al borrar sobre esa tabla inserte en la tabla CTRL_PAISES los valores correspondientes de usuario y fecha, y en el atributo OPERACION insertar el valor 'AFTER DELETE'. Creamos el trigger comentado en el ejercicio con el usuario gestor: CREATE OR REPLACE TRIGGER ejer20 AFTER DELETE ON gestor.paises FOR EACH ROW DECLARE

v_user VARCHAR2(25); BEGIN SELECT USER INTO v_user FROM DUAL; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'AFTER D ELETE'); END ejer20; / SQL> conn gestor Enter password: Connected. SQL> @'paises/ejer20.sql'; Trigger created. Comprobamos con ambos usuarios que el trigger funciona correctamnete, pr eviamente vuelvo a aadir los dos paises que habiamos borrado antes para realizar las pruebas del trigger anterior: SQL> INSERT INTO paises VALUES (5, 'Brasil', 'Brasilia', 625000) ; 1 row created. SQL> INSERT INTO paises VALUES (6, 'Francia', 'Paris', 1200000); 1 row created. Borramos una fila con el usuario GESTOR: SQL> show user; USER is "GESTOR" SQL> delete from paises where cod_pais = 6 1 row deleted. Borramos la segunda con el usuario AKSEN: SQL> conn aksen; Enter password: Connected. SQL> delete from gestor.paises where cod_pais = 5; 1 row deleted. Y comprobamos que el trigger ha aadido dos nuevas filas dentro de ctrl_pa ises con los nuevos borrados: SQL> select * from ctrl_paises; USUARIO FECHA OPERACION ------------------------- --------- -------------------GESTOR 07-MAR-12 BEFORE DELETE AKSEN 07-MAR-12 BEFORE DELETE GESTOR 08-MAR-12 AFTER DELETE AKSEN 08-MAR-12 AFTER DELETE Podemos observar las cuatro filas que tenemos, las dos ltimas equivalen a la insercin que ha realizado el trigger que hemos creado en este ejercicio que es de tipo AFTER.

21. Programe ahora un disparador a nivel de fila de tipo BEFORE sobre la tabla d e Pases, que al borrar cada pas inserte en la tabla CTRL_PAISES los valores correspondient es de usuario y fecha, y en el atributo OPERACION insertar el valor 'BEFORE DELETE fila: PPPP con capital en CCCC'. Los valores de PPPP y CCCC sern los valores del pas y su capital correspondientes a la fila afectada. Para comprobar su funcionamiento borre un pas y posteriormente examine la tabla C TRL_PAISES. Modifico el campo OPERACION de la tabla PAISES para aumentar su tamao y n o tener problemas a la hora de insertar el mensaje requerido: SQL> ALTER TABLE ctrl_paises MODIFY (operacion varchar2(200)); Table altered. Creamos el trigger segn lo que se nos pide: CREATE OR REPLACE TRIGGER ejer21 BEFORE DELETE ON gestor.paises FOR EACH ROW DECLARE v_user VARCHAR2(25); BEGIN SELECT USER INTO v_user FROM DUAL; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'BEFORE DELETE fila: ' :OLD.nombre ' con capital en ' :OLD.capital); END ejer21; / SQL> @'paises/ejer21.sql'; Trigger created. Insertamos dos paises de prueba como en los ejercicios anteriores: SQL> INSERT INTO paises VALUES (5, 'Brasil', 'Brasilia', 625000) ; 1 row created. SQL> INSERT INTO paises VALUES (6, 'Francia', 'Paris', 1200000); 1 row created. Y primero con el usuario GESTOR borramos uno y luego con AKSEN el otro: Borramos una fila con el usuario GESTOR: SQL> show user; USER is "GESTOR" SQL> delete from paises where cod_pais = 5; 1 row deleted. Borramos la segunda con el usuario AKSEN: SQL> conn aksen;

Enter password: Connected. SQL> delete from gestor.paises where cod_pais = 6; 1 row deleted. A continuacin comprobamos el estado de la tabla CTRL_PAISES, que adems de insertar por cada pais borrado el nuevo mensaje, tambin insertar las filas de los anteriores trigger que siguen habilitados: SQL> select * from ctrl_paises; USUARIO ------GESTOR AKSEN GESTOR AKSEN GESTOR apital en Brasilia GESTOR GESTOR AKSEN capital en Paris AKSEN AKSEN FECHA -----07-MAR-12 07-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 OPERACION ---------BEFORE DELETE BEFORE DELETE AFTER DELETE AFTER DELETE BEFORE DELETE fila: Brasil con c BEFORE DELETE AFTER DELETE BEFORE DELETE fila: Francia con BEFORE DELETE AFTER DELETE

10 rows selected.

22. De manera similar al ejercicio anterior, cree un disparador anivel de fila d e tipo AFTER sobre la tabla de Pases, que tras borrar un pas inserte en la tabla CTRL_PAISES lo s valores correspondientes de usuario y fecha, y en el atributo OPERACION insertar el valor 'AFTER DELETE fila: PPPP con capital en CCCC'. Creamos el trigger segn lo que se nos pide, esta vez de tipo AFTER: CREATE OR REPLACE TRIGGER ejer22 AFTER DELETE ON gestor.paises FOR EACH ROW DECLARE v_user VARCHAR2(25); BEGIN SELECT USER INTO v_user FROM DUAL; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'AFTER D ELETE fila: ' :OLD.nombre ' con capital en ' :OLD.capital); END ejer22; / SQL> @'paises/ejer22.sql'; Trigger created.

Volvemos a insertar las filas para comprobar que con cada usuario se eje cuta este nuevo trigger y evidentemente los anteriores que hemos creado: SQL> INSERT INTO paises VALUES (5, 'Brasil', 'Brasilia', 625000) ; 1 row created. SQL> INSERT INTO paises VALUES (6, 'Francia', 'Paris', 1200000); 1 row created. Y primero con el usuario GESTOR borramos uno y luego con AKSEN el otro: Borramos una fila con el usuario GESTOR: SQL> show user; USER is "GESTOR" SQL> delete from paises where cod_pais = 5; 1 row deleted. Borramos la segunda con el usuario AKSEN: SQL> conn aksen; Enter password: Connected. SQL> delete from gestor.paises where cod_pais = 6; 1 row deleted. Comprobamos el estado de la tabla CTRL_PAISES que debe tener, adems de to das las anteriores, los nuevos valores que nos inserta este trigger y todos los anteriores sobre esta e jecucin: SQL> select * from ctrl_paises; USUARIO ------GESTOR AKSEN GESTOR AKSEN GESTOR apital en Brasilia GESTOR GESTOR AKSEN capital en Paris AKSEN AKSEN GESTOR apital en Brasilia GESTOR GESTOR pital en Brasilia GESTOR AKSEN capital en Paris AKSEN AKSEN FECHA ----07-MAR-12 07-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 08-MAR-12 OPERACION ---------------------BEFORE DELETE BEFORE DELETE AFTER DELETE AFTER DELETE BEFORE DELETE fila: Brasil con c BEFORE DELETE AFTER DELETE BEFORE DELETE fila: Francia con BEFORE DELETE AFTER DELETE BEFORE DELETE fila: Brasil con c BEFORE DELETE AFTER DELETE fila: Brasil con ca AFTER DELETE BEFORE DELETE fila: Francia con BEFORE DELETE AFTER DELETE fila: Francia con c

apital en Paris AKSEN 08-MAR-12 AFTER DELETE 18 rows selected.

23. Inserte en la tabla de pases todos aquellos que empiecen por la letra U : Ucrani a (con capital en Kiev), Uganda (con capital en Kampala), Uruguay (con capital en Montevideo) y Uzbekistn (con capital en Tashkent). Localice en un mapa la situacin de estos pases si lo desconoce, y compruebe si se ha disparado algn trigger al ins ertar dicha informacin. Creamos las instrucciones para realizar las insercciones en la tabla pai ses: INSERT INSERT INSERT INSERT INTO INTO INTO INTO paises paises paises paises VALUES VALUES VALUES VALUES (5, (6, (7, (8, 'Ucrania', 'Kiev', 555000); 'Uganda', 'Kampala', 125000); 'Uruguay', 'Montevideo', 225000); 'Uzbekistn', 'Tashkent', 95000);

Y las insertamos: SQL> @'paises/ejer23.sql'; 1 1 1 1 row row row row created. created. created. created.

Comprobamos el nuevo estado de la tabla paises: SQL> select * from paises; COD_PAIS NOMBRE CAPITAL PRESUPUESTO ------------------------------1 Espa??a Madrid 1500000 2 Italia Roma 1250000 3 Portugal Lisboa 750000 4 Alemania Berlin 1500000 6 Uganda Kampala 125000 7 Uruguay Montevideo 225000 5 Ucrania Kiev

555000 8 95000 8 rows selected. Evidentemente no ha saltado ningun trigger ya que si lo comprobamos sobr e la tabla PAISES solo estn los trigger de tipo DELETE que hemos creado en los anteriores ejercicios: SQL> select trigger_name, status, trigger_type, triggering_event , table_name from user_triggers where table_name='PAISES'; TRIGGER_NAME NG_EVENT ------------------EJER19 DELETE EJER20 DELETE EJER21 DELETE EJER22 DELETE STATUS TRIGGER_TYPE TRIGGERI TABLE_NAME -------------------------------------ENABLED BEFORE EACH ROW PAISES ENABLED AFTER EACH ROW PAISES ENABLED BEFORE EACH ROW PAISES ENABLED AFTER EACH ROW PAISES Uzbekist??n Tashkent

24. Borre con una sola sentencia DELETE todos los pases que empiezan por la letra 'U'. Compruebe que en la tabla CTRL_PAISES se han insertado 10 filas y examine cuntas veces se ha ejecutado cada uno de los 4 disparadores que existen sobre esa tabla . Previamente antes de continuar vaciar la tabla de control CTRL_PAISES par a comprobar que filas se insertan nuevas y que todo es correcto: SQL> delete from ctrl_paises; 18 rows deleted. Creamos la sentencia que borra todos los paises que empiecen con la letr a 'U': SQL> show user USER is "GESTOR" SQL> delete from paises where nombre like 'U%'; 4 rows deleted. Comprobamos de nuevo el estado de la tabla CTRL_PAISES: SQL> select * from ctrl_paises;

USUARIO ------GESTOR da con capital en Kampala GESTOR GESTOR a con capital en Kampala GESTOR GESTOR uay con capital en Montevideo GESTOR GESTOR ay con capital en Montevideo GESTOR GESTOR nia con capital en Kiev GESTOR GESTOR ia con capital en Kiev GESTOR GESTOR kist??n con capital en Tashkent GESTOR GESTOR ist??n con capital en Tashkent GESTOR

FECHA ----09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12

OPERACION ---------------------BEFORE DELETE fila: Ugan BEFORE DELETE AFTER DELETE fila: Ugand AFTER DELETE BEFORE DELETE fila: Urug BEFORE DELETE AFTER DELETE fila: Urugu AFTER DELETE BEFORE DELETE fila: Ucra BEFORE DELETE AFTER DELETE fila: Ucran AFTER DELETE BEFORE DELETE fila: Uzbe BEFORE DELETE AFTER DELETE fila: Uzbek AFTER DELETE

16 rows selected. Como vemos, en esta accin de borrado se han insertado 16 filas en vez de las 10 que nos indica el enunciado. Esto se produce porque los triggers creados anteriormente los he hecho tambin ha nivel de fila en vez de a nivel de sentencia por lo que les voy a editar y a repetir este proceso para comprobar que realmente al borrar los paises en la tabla CTRL_PAISES quedan 10 filas afectadas. Simplemente para editar los trigg ers anteriores lo que he hecho es comentar las lineas donde se indicaba la accin de fila por fila (FOR EACH ROW). Por lo que les edito y los vuelvo a crear: SQL> @'paises/ejer19'; Trigger created. SQL> @'paises/ejer20'; Trigger created. Insertamos de nuevo los paises: SQL> @'paises/ejer23'; 1 row created. 1 row created. 1 row created.

1 row created. Vaciamos la tabla CTRL_PAISES para comprobar que se quedan las filas des eadas: SQL> delete from ctrl_paises; 16 rows deleted.

Y volvemos a realizar la accin de borrado sobre todos los paises que empi ezan por 'U': SQL> delete from paises where nombre like 'U%'; 4 rows deleted. Comprobamos de nuevo el estado de la tabla CTRL_PAISES: SQL> select * from ctrl_paises; USUARIO ------GESTOR GESTOR nia con capital en Kiev GESTOR ia con capital en Kiev GESTOR da con capital en Kampala GESTOR a con capital en Kampala GESTOR uay con capital en Montevideo GESTOR ay con capital en Montevideo GESTOR kist??n con capital en Tashkent GESTOR ist??n con capital en Tashkent GESTOR 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 09-MAR-12 BEFORE DELETE fila: Ugan AFTER DELETE fila: Ugand BEFORE DELETE fila: Urug AFTER DELETE fila: Urugu BEFORE DELETE fila: Uzbe AFTER DELETE fila: Uzbek AFTER DELETE 09-MAR-12 AFTER DELETE fila: Ucran FECHA ----09-MAR-12 09-MAR-12 OPERACION ---------------------BEFORE DELETE BEFORE DELETE fila: Ucra

10 rows selected.

En la primar tabla podemos ver, que cada trigger se ha ejecutado 4 veces , una vez por cada ejecucin de borrado que se ha realizado, ya que todos los disparadores estaban programados a nivel de fila En la segunda podemos ver como se ejecuta primero el trigger BEFORE (eje r19) cuando es de tipo SENTECIA luego se ejecuta, por cada pais borrado el trigger BEFORE (ejer21) y el AFTER(eje22), recu erdo que ambos son de tipo FOR EACH ROW (afectan

a cada fila borrada) y por ltimo se ejecuta el trigger AFTER (ejer20) que tambin es de tipo SENTENCIA .

25. Se desea asegurar que los pases de la zona Euro no tengan un presupuesto para fines sociales (tabla de Pases) inferior a un milln de Euros. Para ello, al insertar estos pases o al actualizar su presupuesto deber comprobar si el presupuesto que se pretende dejar en la tabla es menor a esa cantidad. En caso afirmativo debe poner el presupuest o mnimo e insertar en la tabla CTRL_PAISES un mensaje aclaratorio que indique el pas y la cantidad que se le ha aadido a su p resupuesto para llegar al mnimo. Los 12 pases de la zona Euro son: Espaa, Portugal, Italia, Grecia, Austria, Aleman ia, Finlandia, Irlanda, Blgica, Holanda, Luxemburgo y Francia. Modifico Portugal, que lo tenia ya insertado de antes, para que su presp uesto mnimo sea de 1.000.000 SQL> update paises set presupuesto=1000000 where cod_pais=3; 1 row updated. Vaciamos la tabla de CTRL_PAISES para ver los cambios que obtendremos ah ora: SQL> delete from ctrl_paises; 10 rows deleted.

Lo primero que har ser crear el trigger para que cada vez que se introduzc a o se modifique uno de estos paises en la tabla paises se le compruebe el presupuesto y de ser menor a 1.000 .000 se le estableza el mnimo que equivale a dicha cantidad. Adems se insertar la accin dentro de la tabla de control CTRL_PAISES. El principal problema con este trigger es al insertar o actualizar una f ila sobre la tabla en la que se est ejecutando el trigger. Es decir como el trigger est actuando sobre la tabla PAISES y es en esa misma sobre la que deseamos actualizar o insertar un nuevo dato da problema de "mutacin en la tabla". El segundo punto, el insertar una nueva fila dentro de la tabla CTRL_PAISES no da ningn problema y se ejecuta sin invonenientes. Para solucionar el tema de las tablas mutantes, segn lo investigado, debe ra de valer con realizar le trigger tipo AFTER, es decir que se "dispare" tras inserccin o actualizacin, en este ca so, pero an as no consigo que deje de dar el problema, y si planteo el siguiente trigger persiste el proble ma de las tablas mutantes:

CREATE OR REPLACE TRIGGER ejer25 AFTER INSERT OR UPDATE OF presupuesto ON gestor.paises FOR EACH ROW WHEN (NEW.nombre = 'Grecia' OR NEW.nombre = 'Austri a' OR NEW.nombre = 'Finlandia' OR NEW.nombre = 'Irlanda' OR NEW.nombre = 'Blgica' OR NEW.nombre = ' Holanda' OR NEW.nombre = 'Luxemburgo' OR NEW.nombre = 'Francia' OR NEW.nombre = 'Espaa' OR NEW.nombre = 'A lemania' OR NEW.nombre = 'Italia' OR NEW.nombre = 'Portugal') DECLARE v_user VARCHAR2(25); val_min gestor.paises.presupuesto%TYPE := 1000000; diff gestor.paises.presupuesto%TYPE; BEGIN SELECT USER INTO v_user FROM DUAL; IF :NEW.presupuesto < val_min THEN UPDATE gestor.paises SET presupuesto = val_min WHERE cod_pais = :NEW.cod_pais; diff:= val_min - :NEW.presupuesto; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'Presupu esto actualizado en ' :NEW.nombre ', no llegaba al minimo y le faltaban ' diff); END IF; END ejer25; / Lo creamos: SQL> @'paises/ejer25_1.sql'; Trigger created. Intentamos insertar una nueva fila y podemos ver el error que se muestra : SQL> INSERT INTO paises VALUES (5, 'Grecia', 'Atenas', 555000); INSERT INTO paises VALUES (5, 'Grecia', 'Atenas', 555000) * ERROR at line 1: ORA-04091: table GESTOR.PAISES is mutating, trigger/function may not see it ORA-06512: at "GESTOR.EJER25", line 10 ORA-04088: error during execution of trigger 'GESTOR.EJER25'

Esta vez actualizandola: SQL> update paises set presupuesto = 999999 where cod_pais = 1; update paises set presupuesto = 999999 where cod_pais = 1 * ERROR at line 1: ORA-04091: table GESTOR.PAISES is mutating, trigger/function may not see it ORA-06512: at "GESTOR.EJER25", line 10 ORA-04088: error during execution of trigger 'GESTOR.EJER25'

Tras muchas prubas con triggers tipo before, after, buscando soluciones haciendo dobles triggers o aislando alguna de las ejecuiones en paquetes o procedimientos, lo nico que me ha servido para a cercarme a la realidad la cual pedia el ejercicio es mediante el uso de la clausula PRAGMA AUTONOMOUS_TRANSACTION, la cual ex plico en el ejercicio siguiente, pero viene a ser que nos permite aislar transacciones dentro de un trigger de modo que po dremos ejecutar el siguiente: CREATE OR REPLACE TRIGGER ejer25 BEFORE INSERT OR UPDATE OF presupuesto ON gestor.paises FOR EACH ROW WHEN (NEW.nombre = 'Grecia' OR NEW.nombre = 'Austri a' OR NEW.nombre = 'Finlandia' OR NEW.nombre = 'Irlanda' OR NEW.nombre = 'Blgica' OR NEW.nombre = ' Holanda' OR NEW.nombre = 'Luxemburgo' OR NEW.nombre = 'Francia' OR NEW.nombre = 'Espaa' OR NEW.nombre = 'A lemania' OR NEW.nombre = 'Italia' OR NEW.nombre = 'Portugal') DECLARE PRAGMA AUTONOMOUS_TRANSACTION; v_user VARCHAR2(25); val_min gestor.paises.presupuesto%TYPE := 1000000; diff gestor.paises.presupuesto%TYPE; BEGIN SELECT USER INTO v_user FROM DUAL; diff:= val_min - :NEW.presupuesto; IF INSERTING AND :NEW.presupuesto < val_min THEN commit; INSERT INTO gestor.paises VALUES (:NEW.cod_pais, :NEW.nombre, :N EW.capital, val_min); commit; INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'Presupu esto actualizado en ' :NEW.nombre ', no llegaba al minimo y le faltaban ' diff); commit; RAISE_APPLICATION_ERROR(-20000, :NEW.nombre ' no llegaba al min imo, por lo que se le ha insertado con el presupuesto minimo'); END IF; IF UPDATING AND :NEW.presupuesto < val_min THEN INSERT INTO gestor.ctrl_paises VALUES (v_user, SYSDATE, 'Se ha i ntentado actualizar el presupuesto de ' :NEW.nombre ', pero no se hizo por que le faltaban para el mi nimo la cantidad de ' diff ' Euros'); commit; RAISE_APPLICATION_ERROR(-20001, 'No se puede actualizar presupue sto de paises de la UE a menos de 1.000.000 de euros'); END IF; END ejer25; / Este trigger tiene un "problema" y es que al hacer INSERT como se realiz a antes de la inserccin hay que hacer COMMIT y da

problemas con la clave primaria, pero la fila se inserta correctamente a unque da un mensaje de error, pero para eso lo he personalizado y mostrado el que me interesa que nos informa de que el pa is se ha insertado con los valores minimos de presupuesto. Cuando hacemos UPDATE no actualiza el PRESUPUESTO del pais, si no que no s indica que no podemos actualizar a menos de 1.000.000 de el PRESUPUESTO y nos lo audita en la tabla CTRL_PAISES con la diferencia hasta el milln, esta accin la realiza siempre tanto en INSERT como en UPDATE sin ningn problema. De modo que lo volvemos a crear: SQL> @'paises/ejer25_1.sql'; Trigger created. Y comprobamos que pasa si insertamos un nuevo pais de la UE que no cumpl e con las reglas de presupuesto minimo: SQL> INSERT INTO paises VALUES (5, 'Grecia', 'Atenas', 555000); INSERT INTO paises VALUES (5, 'Grecia', 'Atenas', 555000) * ERROR at line 1: ORA-20000: Grecia no llegaba al minimo, por lo que se le ha inse rtado con el presupuesto minimo ORA-06512: at "GESTOR.EJER25", line 18 ORA-04088: error during execution of trigger 'GESTOR.EJER25' Nos informa de que Grecia no llega al minimo y que se le ha insertado co n el presupuesto minimo: SQL> select * from paises where cod_pais = 5; COD_PAIS STO -------------------------------------------------------5 Grecia Atenas 1000000 Del mismo modo si comprobamos la tabla CTRL_PAISES veremos como nos info rma que Grecia se ha insertado y el presupuesto que le faltaba para el minimo: SQL> select * from ctrl_paises; USUARIO FECHA OPERACION ----------------------------------------------------------------------------------------------------------------GESTOR 12-MAR-12 Presupuesto actu alizado en Grecia, no llegaba al minimo y le faltaban 445000 NOMBRE CAPITAL PRESUPUE

Del mismo modo, el trigger nos informar si se intenta ACTUALIZAR un presu puesto por debado de lo permitido, que no se puede y lo auditar en CTRL_PAISES: SQL> UPDATE paises SET presupuesto = 999999 WHERE cod_pais = 5; UPDATE paises SET presupuesto = 999999 WHERE cod_pais = 5 * ERROR at line 1: ORA-20001: No se puede actualizar presupuesto de paises de la UE

a menos de 1.000.000 de euros ORA-06512: at "GESTOR.EJER25", line 26 ORA-04088: error during execution of trigger 'GESTOR.EJER25' Y comrpobamos que en la tabla CTRL_PAISES ha almacenado los datos pertin entes al intento de actualizacin de un dato no permitido: SQL> select * from ctrl_paises; USUARIO FECHA OPERACION ----------------------------------------------------------------------------------------------------------------GESTOR 12-MAR-12 Presupuesto actu alizado en Grecia, no llegaba al minimo y le faltaban 445000 GESTOR 12-MAR-12 Se ha intentado actualizar el presupuesto de Grecia, pero no se hizo por que le faltaban para el minimo la cantidad de 1 Euros

Por ltimo vamos a comprobar que esto solo afecta a los paises de la UE qu e se nos especificaba y cuando su PRESUPESTO es menor a 1.000.000 de euros. Por ejemplo intentamos insertar un pas que no corresponde con los de la U E con cualquier presupuesto: SQL> INSERT INTO paises VALUES (6, 'Brasil', 'Brasilia', 750000) ; 1 row created. SQL> select * from paises; COD_PAIS NOMBRE CAPITAL PRESUPUESTO ----------------------------------------------------1 Espa??a Madrid 1000000 2 1000000 3 1000000 4 1000000 5 1000000 6 750000 6 rows selected. Vemos como se ha insertado Brasil sin problemas. Tambin, si insertamos un pais ue pertenzca a la UE con un presupuesto vlid o no tenemos ningn problema: SQL> INSERT INTO paises VALUES (7, 'Francia', 'Paris', 1250000); 1 row created. SQL> select * from paiseS; COD_PAIS NOMBRE CAPITAL PRESUPUESTO Brasil Brasilia Grecia Atenas Alemania Berlin Portugal Lisboa Italia Roma

----------------------------------------------------1 Espa??a Madrid 1000000 2 1000000 3 1000000 4 1000000 5 1000000 6 750000 7 1250000 7 rows selected. Lo mismo ocurre, si queremos actualizar un presupuesto de un pais que si cumpla las normas: SQL> UPDATE paises SET presupuesto = 1000001 WHERE nombre = 'Fra ncia'; 1 row updated. SQL> select * from paises; COD_PAIS NOMBRE CAPITAL PRESUPUESTO ----------------------------------------------------1 Espa??a Madrid 1000000 2 1000000 3 1000000 4 1000000 5 1000000 6 750000 7 1000001 7 rows selected. Francia Paris Brasil Brasilia Grecia Atenas Alemania Berlin Portugal Lisboa Italia Roma Francia Paris Brasil Brasilia Grecia Atenas Alemania Berlin Portugal Lisboa Italia Roma

26. Modifique el disparador anterior para que al final haga un COMMIT. Qu ocurre? Lo primero que tenemos que saber que un trigger no puede emitir ninguna orden de control de transacciones, como lo es un COMMIT. Ya que un trigger se activa como parte de la ejecucin de la orden lo prov

oc. Cuando la orden que provoca el trigger es confirmada o cancelada, se confirma o cancela tambin el trabajo que reali za el trigger. La nica forma de modificar el trigger para aadirle un COMMIT es usando "PR AGMA AUTONOMOUS_TRANSACTION": Donde el trigger se ejecuta en una transaccin diferente. Por la documentacin revisada, dicen que no es muy recomendable us ar este sistema, ya que: -->Si queremos realizar varios cambios seguidos dentro d e la misma transaccin no tendremos acceso a ellos (es una transaccin diferente cada vez), este es el motivo por el que no la hemos podido usar nosotros ya que tenemos dos operaciones en el mismo trigger. -->Si el trigger falla y se hace rollback no nos enterar emos (no deshar la transaccin en que se ha disparado el trigger) No lo he realizado de nuevo ya que el trigger que he ejecutado en el eje rcicio anterior cumple con estos requisitos de usar COMMIR dentro de l.

27. Borre las tablas prestando especial atencin al orden en el que deben borrarse . Comprobamos las tablas de tiene el usuario GESTOR: SQL> select table_name from all_tables where owner='GESTOR'; TABLE_NAME ---------------CTRL_PAISES PAISES REGIONES CENSO ACTIVIDADES ADOPTAR CTRL_ACTIVIDADES 7 rows selected. Para eliminar una tabla determinada, usar la siguiente instruccin, con la que borraremos las tablas de control ya que son las nicas que no tiene claves ajenas en ellas: SQL> DROP TABLE CTRL_ACTIVIDADES; SQL> DROP TABLE CTRL_PAISES; Para el resto de las relaciones se presentan de manera diferente ya que la relacin que va a ser eliminada est referenciada por claves ajenas en otras tablas o relaciones. En este caso lo vamos hacer se debe hacer la llamada de la siguiente man era: SQL> DROP TABLE PAISES CASCADE CONSTRAINTS; SQL> DROP TABLE REGIONES CASCADE CONSTRAINTS; SQL> DROP TABLE CENSO CASCADE CONSTRAINTS;

SQL> DROP TABLE ACTIVIDADES CASCADE CONSTRAINTS; SQL> DROP TABLE ADOPTAR CASCADE CONSTRAINTS; De esta manera se eliminarn todas las tuplas en otras relaciones que refe rencien a la clave primaria de la relacin a ser eliminada. Si no se incluye el parmetro CASCADE CONSTRAINTS y existe alguna referenc ia a una tupla que se eliminar, ORACLE nos dar un mensaje de error y no eliminar la tabla.