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 ;