Bases de Données, 2eme Année 2013-2014 TD 6 PLSQL (Paquetages et déclencheurs) Question 1. Afin d améliorer le service marketing et la gestion de son stock, la société VidéoScope souhaite avoir à sa disposition à tout moment une série de données statistiques relatives à sa base. Créer un package statistics qui rassemble les procédures et fonctions permettant de savoir : 1) Le nombre de films pour lesquels on ne possède aucun exemplaire. 2) Le pourcentage des exemplaires pour lesquels on n a jamais signalé de problèmes. Question 2. On considère la table TRACE (numlog, numexemplaire, message,datelocation,dateenvoi), où numlog est un entier, message une chaîne de caractères, datelocation et dateenvoi des dates. Soit la fonction nbvallog (qui compte le nombre de lignes de la table TRACE) définie par : CREATE OR REPLACE FUNCTION nbvallog RETURN NUMBER AS nbval NUMBER; SELECT COUNT(*) INTO nbval FROM TRACE; RETURN nbval; On considère maintenant les quatre déclencheurs ci-dessous. Lors d une insertion ou mise à jour dans la table LOCATION, quelles valeurs sont ajoutées dans la table TRACE? Que peut-on en déduire sur l ordre d activation des déclencheurs d une même table, en fonction de leurs types? En particulier, que se passe-t-il si l'on fait les requêtes suivantes (mo a loué l'exemplaire 12 le 5 octobre et les exemplaires 11 et 13 le 6 octobre, que l'on croyait avoir envoyés ; en fait tout est envoyé le 7 octobre) : Insert into location values ('mo', 12, '05-OCT-2012', '06-OCT-2012', NULL); Insert into location values('mo', 11, '06-OCT-2012', NULL, NULL); Insert into location values('mo', 13, '06-OCT-2012', NULL, NULL); Update location set dateenvoi='07-oct-2012' where login='mo'; 1
Déclencheur TRIG_1 CREATE OR REPLACE TRIGGER TRIG_1 AFTER INSERT OR UPDATE OF dateenvoi ON LOCATION FOR EACH ROW (nbvallog+1, :NEW.numExemplaire, fin ligne, :NEW.dateLocation, NULL); END IF; (nbvallog+1,:new.numexemplaire, fin ligne,:new.datelocation, :NEW.dateEnvoi); END IF; Déclencheur TRIG_3 CREATE OR REPLACE TRIGGER TRIG_3 BEFORE INSERT OR UPDATE OF dateenvoi ON LOCATION FOR EACH ROW (nbvallog+1,null, debut ligne,null,null); END IF; (nbvallog+1, :OLD.numExemplaire, debut ligne, :OLD.dateLocation, :OLD.dateEnvoi); END IF; Déclencheur TRIG_2 CREATE OR REPLACE TRIGGER TRIG_2 AFTER INSERT OR UPDATE OF dateenvoi ON LOCATION (nbvallog+1,null, fin insertion, NULL,NULL); END IF; (nbvallog+1,null, fin modif, NULL,Null); END IF; Déclencheur TRIG_4 CREATE OR REPLACE TRIGGER TRIG_4 BEFORE INSERT OR UPDATE OF dateenvoi ON LOCATION (nbvallog+1,null, Debut insertion, NULL, NULL); END IF; (nbvallog+1,null, Debut modif, NULL, NULL); END IF; Question 3. Comme dans la Question 2, le responsable de la société VidéoScope souhaite améliorer davantage la qualité de ses services proposés. Ecrivez un déclencheur qui doit envoyer un message d alerte lorsqu'un exemplaire réservé par un client n a pas été expédié dans un délai de 48 heures. Question 4. Créer un déclencheur qui empêche la suppression d une ligne de la table film par une personne non autorisée et qui envoie un message d'erreur, par exemple, «Attention! Utilisateur non autorisé». 2
Question 1. La spécification du package : ----------CORRIGE TD 6---------- DROP PACKAGE stat; CREATE PACKAGE stat AS FUNCTION nbrefilmsnul RETURN NUMBER; PROCEDURE percent; end stat; Le corps du package : CREATE OR REPLACE PACKAGE BODY stat IS FUNCTION nbrefilmsnul RETURN NUMBER IS aux number; dbms_output.enable; select count (*) into aux from ens2004.film where numfilm NOT IN (select numfilm from ens2004.exemplaire) ; return aux; END nbrefilmsnul; PROCEDURE percent IS aux1 number; aux2 number; dbms_output.enable; select count (*) into aux1 from ens2004.exemplaire where probleme IS NULL; select count (*) into aux2 from ens2004.exemplaire; dbms_output.put_line(aux1aux2); END percent; end stat; Attention : Expliquer aux élèves comment exécuter un package : Pour voir les résultats dans un autre bloc : n:= stat. Nbrefilmsnul ; stat. Percent ; Question 2 : Le but ici est de faire comprendre aux étudiants quand se déclenche les triggers et les différences entre old et new... 3
Supposons que la table TRACE est vide au départ. Ainsi, les valeurs insérées dans cette table permettent de savoir dans quel ordre les déclencheurs sont activés lorsqu ils sont de type différent. Pour cela, observez, par exemple, comment la table TRACE est remplie lors les deux insertions et la mise à jour suivantes : Insert into location values ('mo', 12, '05-OCT-2012', '06-OCT-2012', NULL); 1 row created. select * from trace; Insert into location values('mo', 11, '06-OCT-2012', NULL, NULL); 1 row created. select * from trace; 5 Debut insertion 6 debut ligne 7 11 fin ligne 06-OCT-12 8 fin insertion Insert into location values('mo', 13, '06-OCT-2012', NULL, NULL); select * from trace; (pareil, juste là pour la suite!) 5 Debut insertion 6 debut ligne 7 11 fin ligne 06-OCT-12 8 fin insertion 9 Debut insertion 10 debut ligne 11 13 fin ligne 06-OCT-12 12 fin insertion 4
Update location set dateenvoi='07-oct-2012' where login='mo'; 3 rows updated. select * from trace; 5 Debut insertion 6 debut ligne 7 11 fin ligne 06-OCT-12 8 fin insertion 9 Debut insertion 10 debut ligne 11 13 fin ligne 06-OCT-12 12 fin insertion 13 Debut modif 14 1 05-OCT-12 06-OCT-12 15 12 fin ligne 05-OCT-12 07-OCT-12 16 11 debut ligne 06-OCT-12 17 11 fin ligne 06-OCT-12 07-OCT-12 18 13 debut ligne 06-OCT-12 19 13 fin ligne 06-OCT-12 07-OCT-12 20 fin modif Question 3. Voici un trigger (parler de oldnew dans when ) DROP TRIGGER alertergerant2; CREATE TRIGGER alertergerant2 AFTER UPDATE ON location for each row when (new.dateenvoi>old.datelocation+2) DECLARE DBMS_OUTPUT.PUT_LINE( Attention, délais de livraison très longue ); Trigger created. Insert into location values( charlie, 12, 10-JAN-2012,NULL, NULL); Insert into location values( charlie, 11, 11-JAN-2012, 12-JAN-2012, NULL); Insert into location values( charlie, 11, 01-OCT-2012, 02-OCT-2012, 2- OCT-2012 ); Insert into location values( mo, 11, 06-OCT-2012, NULL, NULL); 5
SQL> Update location 2 Set dateenvoi=sysdate where login='mo'; --sysdate : lundi 9 octobre Attention, délais de livraison très longue 1 row updated. SQL> Update location 2 Set dateenvoi='11-jan-2012' where login='charlie' and numexemplaire=12; 1 row updated. Question 4. On présente trois solutions : 1. Voici une alerte simple (la ligne sera supprimée) : CREATE OR REPLACE TRIGGER alerte BEFORE DELETE ON filmbis DBMS_OUTPUT.enable ; DBMS_OUTPUT.PUT_LINE( Attention vous allez supprimer des lignes de la table film ); END ; 2. Voici une exception qui envoie un message d alerte, mais la ligne sera supprimée : CREATE OR REPLACE TRIGGER interd_delete1 BEFORE DELETE ON filmbis DECLARE MonException EXCEPTION ; PRAGMA EXCEPTION_INIT(MonException, -20001) ; IF USER!='DUPONT' THEN RAISE MonException ; END IF; EXCEPTION WHEN MonException THEN DBMS_OUTPUT.PUT_LINE('Attention, Utilisateur non autorisé'); 3. Voici une exception qui envoie un message d erreur et qui empêche de supprimer la ligne. CREATE OR REPLACE TRIGGER interd_delete2 BEFORE DELETE ON filmbis DECLARE MonException EXCEPTION ; IF USER!='DUPONT' THEN RAISE MonException ; 6
END IF; EXCEPTION WHEN MonException THEN RAISE_APPLICATION_ERROR(-20001, 'Attention, Utilisateur non autorisé'); 7