TD6 – Bases de données
Transcription
TD6 – Bases de données
IUP MIAGE 2 – 2006/2007 TD6 – Bases de données novembre 2006 Exercice 1 : on reprend l’énoncé de l’exercice 1 du TD précédent : Une société de services gère de nombreux projets, et chacun des employés de la société peut travailler simultanément sur plusieurs de ces projets. Il est intéressant de connaı̂tre le temps passé par chaque personne sur chaque projet. De plus, lorsque l’on démarre un projet, il est indispensable d’estimer le temps nécessaire pour le réaliser. Dans cet exercice, cette estimation est un nombre d’heures. On mémorise pour une semaine donnée, le nombre d’heures passées par une personne sur un projet. Voici les ordres SQL qui ont servi à créer le schéma de la base de donnée : create table PERSONNE( refpers NUMBER(3) constraint personne_pkey primary key, nom VARCHAR2(20) not null, prenom VARCHAR2(20) not null ); create table PROJET( refproj NUMBER(3) constraint projet_pkey primary key, titre VARCHAR2(20) not null, nb_heures_prevues NUMBER default 0 not null ); create table TACHE( refproj NUMBER(3) constraint tache_projet_fkey references projet, refpers NUMBER(3) constraint tache_pers_fkey references personne, semaine NUMBER(2), constraint tache_pkey primary key (refproj,refpers,semaine), nb_heures NUMBER(2), constraint nb_heures_non_negatif check (nb_heures >= 0), constraint semaine_correcte check (semaine between 1 and 52) ); On désire vérifier que le nombre d’heures effectuées ne dépasse pas (ou pas trop) le nombre d’heures prévues pour la réalisation d’un projet. En cas de dépassement, on écrit un message dans la table TAB_LOG prévue pour recueillir les anomalies constatées lors de la gestion des projets. Le schéma de la table TAB_LOG est TAB_LOG(date_pb, refproj, message) Une première solution est envisagée, qui donne lieu à l’écriture du trigger suivant : 2 IUP MIAGE 2 – 2006/2007 : TD6 – Bases de données create or replace trigger T1 after insert or update on TACHE for each row declare nb_heures_projet, nb_heures_effectuees NUMBER ; begin select nb_heures_prevues into nb_heures_projet from PROJET where :new.refproj = refproj ; select sum(nb_heures) into nb_heures_effectuees from TACHE where :new.refproj = refproj ; if (nb_heures_effectuees > nb_heures_projet) then insert into TAB_LOG values (sysdate(), :new.refproj, ’depassement nb heures’); end if ; end T1; Question 1.1 : Ce trigger compile mais il entraı̂ne une erreur à l’exécution. Laquelle ? (Expliquez ce qui se produit) La précédente solution ne fonctionnant pas, on décide de stocker dans la table PROJET le nombre d’heures effectuées. alter table PROJET add ( nb_heures_effectuees NUMBER(2) not null default 0 ); Question 1.2 : Il y a déjà des lignes dans la table TACHE. Elles n’ont pas été prises en compte dans la table PROJET. Ecrivez la commande SQL qui permet de mettre à jour la table PROJET en calculant les bonnes valeurs pour la colonne nb_heures_effectuees. Question 1.3 : Que faut-il ajouter au code des procédures ajouter_heures_tache et enlever_heures_tache pour que les nombres d’heures effectuées stockés dans PROJET soient cohérents avec ceux stockés dans la table TACHE ? Ne réécrivez pas tout mais seulement le code inséré, en précisant à quel endroit vous l’insérez. Question 1.4 : Ecrivez un trigger sur la table PROJET qui permet d’insérer un message d’erreur dans la table TAB_LOG lorsque le nombre d’heures effectuées dépasse le nombre d’heures prévues. IUP MIAGE 2 – 2006/2007 : TD6 – Bases de données 3 Exercice 2 : on reprend l’énoncé de l’exercice 2 du TD précédent, en le simplifiant. Une formation en informatique organise un championnat de football sur l’université, où chacun peut constituer une équipe, qu’il soit étudiant ou personnel. Toutes les équipes se rencontrent deux fois sur l’année (match aller et match retour, même si tout se fait sur l’université !) Dans cet exercice, le classement des équipes se fera en fonction du nombre de victoires de chaque équipe. Voici les tables qu’ils créent sous Oracle : create table EQUIPE( eref NUMBER(3) constraint equipe_pkey primary key, nom VARCHAR2(20) not null, nb_Victoires NUMBER(3) default 0 not null ); create table MATCH( Receveur NUMBER(3) constraint equipeRec_match_fkey references equipe, Invite NUMBER(3) constraint equipeInv_match_fkey references equipe, Score_Receveur NUMBER(2), Score_Invite NUMBER(2), date_match DATE, constraint match_pkey primary key(receveur, invite), constraint pas_reflexif check(receveur <> invite) ) ; Question 2.1 : Définir un ou plusieurs triggers qui permettent de calculer automatiquement le nombre de victoires de chaque équipe en fonction des modifications (INSERT, DELETE, UPDATE) de la table MATCH. Exercice 3 : Voici une base de données qui permet de stocker des informations sur les disques et leurs interprètes. CATEGORIE ( c_ref, c_libelle) -- c_ref clef primaire -- par exemple (1,’pop-rock’) DISQUE (d_ref, d_titre, d_annee, d_categ) -- d_ref clef primaire, d_categ clef étrangère vers CATEGORIE NOM (n_ref, n_nom, n_prenom); -- un "nom" peut-^ etre une personne ou un groupe n_ref clef primaire CHANSON (c_ref, c_titre, c_annee); -- c_ref clef primaire GROUPE (g_refgroupe, g_refpers) -- la personne telle que n_ref=g_refpers dans la table NOM appartient -- au groupe de reference n_ref=g_refgroupe dans la table NOM -- donc g_refgroupe et g_refpers sont des clefs étrangères sur la table NOM. -- le couple forme la clef primaire. INTERPRETE (i_disque,i_chanson,i_nom) 4 IUP MIAGE 2 – 2006/2007 : TD6 – Bases de données -- la chanson i_chanson est interprétée par i_nom dans le disque i_disque. -- i_disque clef etrangere sur DISQUE, i_nom sur NOM, i_chanson sur CHANSON -- le triplet forme la clef primaire Question 3.1 : Ecrire un trigger qui permet de vérifier qu’un groupe n’est pas membre d’un groupe. Attention, la solution ci-dessous n’est pas possible (cf question 1 de l’exercice précédent) : create or replace trigger verif_groupe after insert or update on groupe for each row declare compteur1 number ; compteur2 number ; begin select count(*) into compteur1 from groupe where g_refgroupe = :new.g_refpers ; select count(*) into compteur2 from groupe where g_refpers = :new.g_refgroupe ; if compteur1+compteur2 <> 0 then raise_application_error(-20104,’un groupe ne peut pas etre membre d’’un groupe’) ; end if ; end verif_groupe ;