Agence de voyages
[45 min]
Une agence de voyage propose des prestations de logement de vacances de type hôtel, location ou gîte. Son catalogue est public et peut être consulté par tous les utilisateurs.
Elle dispose par ailleurs d'un fichier client avec les prestations effectivement vendues, à des prix éventuellement négociés en dessous du prix public. Ces données ne sont accessibles qu'à l'utilisateur "Gerant".
Le schéma UML ci-dessous représente le problème posé. On notera que Code et Numéro sont deux clés naturelles préalablement identifiées (mais il peut y avoir d'autres clés non encore identifiées). le niveau de prestation correspond au nombre d'étoiles de 1 à 5.
Question
Analyser la relation d'héritage et proposer la meilleure solution pour le passage au modèle relationnel.
Solution
L'héritage est complet et exclusif, la classe mère est abstraite. Les deux solutions de transformation par la classe mère et pas les classes filles sont possibles, mais l'héritage par la classe mère est beaucoup plus simple dans ce cas (solution à 3 tables seulement).
On choisit donc une transformation de l'héritage par la classe mère.
Question
Proposer un modèle logique relationnel.
Solution
Prestations (#code:integer, intitule:string, description:string, lieu:string, niveau:integer, prixPublic:float, photo:BLOB, type:{H,L,G}) WITH type NOT NULL
Clients (#numero:integer, nom:string, prenom:string)
Achete (#client=>Clients(numero), #prestation=>Prestation(code), prix:float)
- Constraints : {niveau ≤ 5}
Question
Écrire en algèbre relationnelle la ou les vues induites par la transformation de la relation d'héritage.
Solution
vHotel = Restriction (Prestations, Prestations.type = 'H')
vLocation = Restriction (Prestations, Prestations.type = 'P')
vGite = Restriction (Prestations, Prestations.type = 'G')
Question
Noter que l'intitulé d'une prestation est unique et toujours renseigné d'une part ; et que le niveau de la prestation (nombre d'étoiles), le lieu ainsi le type de logement (hôtel, location ou gîte) permettent de déterminer le prix public d'autre part.
Préciser pourquoi le fait que les prix pratiqués peuvent être négociés en dessous du prix public permet d'écarter la DF Prestation → Prix
dans la relation Achete
.
Énoncer pour chaque relation du schéma la liste des clés et des DF[1].
Solution
Si les prix sont fixes pour tous les clients, alors Prestation → Prix
dans la relation Achete
. Mais comme les prix peuvent être négociés pour chaque client, il faut connaître la prestation et le client pour connaître le prix. Par exemple si le prix public est de 100 et que le client2 a eu 10% de remise alors on obtient dans la relation Achete
: (client1, prestat1, 100) ; (client2, prestat1, 90)
.
Prestations : les clés sont (code) et (intitule)
{code → intitule, description, lieu, niveau, prixPublic, photo, type ; intitule → code, description, lieu, niveau, prixPublic, photo, type ; (niveau, lieu, type) → prixPublic}
Clients : La clé est (numero)
{numero → nom, prenom}
Achete : La clé est (client, prestation)
{(client, prestation) → prix}
Question
En quelle forme normale est le schéma relationnel ? Justifier avec précision. Le schéma est-il redondant ? Si oui donner un exemple, sinon expliquer pourquoi.
Solution
Le schéma est en 2NF.
Le schéma est en 1NF car toutes les relations ont au moins 1 clé et tous les attributs sont atomiques.
Le schéma est en 2NF car :
Pour Prestations et Clients, les clés (
code
), (intitule
), (numero
) sont composées d'un seul attributPour Achete,
prix
ne dépend pas de Clients ou Prestations seulement (car le prix peut être négocié par le client pour chaque prestation donc Prestations ne détermine pasprix
).
Le schéma n'est pas en 3NF car (niveau, lieu, type) → prix
, donc il existe une DFE[2] vers un attribut n'appartenant pas à une clé qui n'est pas issue d'une clé.
La schéma est donc redondant, en effet on aura par exemple :
Question
Écrivez les instructions SQL LDD[3] permettant de créer la base de données PostgreSQL correspondant au schéma relationnel.
Solution
CREATE TABLE Prestations (
pkCode INTEGER PRIMARY KEY,
intitule VARCHAR UNIQUE NOT NULL,
description VARCHAR,
lieu VARCHAR,
niveau INTEGER CHECK (niveau < 6),
prix DECIMAL(4,2),
photo OID,
type CHAR(1) NOT NULL CHECK (type IN ('H','L','G'))
) ;
CREATE TABLE Clients (
pkNumero INTEGER PRIMARY KEY,
nom VARCHAR,
prenom VARCHAR
) ;
CREATE TABLE Achete (
fkClient INTEGER,
fkPrestation INTEGER,
prix DECIMAL (4,2),
PRIMARY KEY (fkClient, fkPrestation),
FOREIGN KEY (fkClient) REFERENCES Clients(pkNumero),
FOREIGN KEY (fkPrestation) REFERENCES Prestations(pkCode)
) ;