# Partie normalisation ## Consignes * Choisir 4 à 5 classes (valider avec le chargé) * Pour chacune d'entre elles * déterminer les DF * déterminer la NF de la table * normaliser la table (i.e. la transformer en 3NF) Partie non-relationnel : rendu éventuellement le 28/06. ## Choix des classes * Voyageur * Billet * Train * Trajet * Gare ## Écriture des DF ### Voyageur ``` Voyageur(#id:integer, nom : string, prenom:string, adresse: string, num_tel:integer[10], num_carte:integer, statut:{voyageur|grandVoyageur|grandVoyageurPlus}, regulier : boolean) avec (id, nom, prenom, adresse, num_tel) NOT NULL, num_carte UNIQUE, (nom,prenom,adresse) KEY, (num_carte NOT NULL AND statut NOT NULL AND regulier) XOR (NOT regulier) ``` * id $\rightarrow$ nom, prénom, adresse, num_tel, num_carte, statut, regulier DF triviale car id est une clé artificielle. * nom, prenom, adresse $\rightarrow$ id, num_tel, num_carte, statut, regulier **Convention** : c'est l'adresse qui permet de discriminer les homonymes dans la BDD, pas le numéro de téléphone. Imaginons un voyageur qui veuille s'inscrire avec son adresse perso puis l'adresse de son entreprise, on crée 2 tuples différents. * num_carte $\rightarrow$ statut, regulier `num_carte` est une clé locale pour la classe représentant un voyageur régulier en réalité, c'est une clé candidate pour tout tuple représentant un voyageur régulier, mais on ne peut pas l'écrire comme clé candidate car la classe admet des voyageurs non réguliers. La table est donc en **2NF**, puisque l'attribut non clé `num_carte` détermine deux autres attributs non clés. Transformation en **3NF** : on crée une table dédiée aux numéros de carte pour supprimer la dépendance gênante. `num_carte` étant optionnel, et non nul seulement si le voyageur est régulier, on n'ajoutera pas l'attribut `regulier` dans cette nouvelle table. ``` Voyageur(#id:integer, nom : string, prenom:string, adresse: string, num_tel:integer[10], num_carte=>Carte) avec (id, nom, prenom, adresse, num_tel) NOT NULL et (nom, prenom, adresse) KEY Carte(#num_carte: int, statut{voyageur|grandVoyageur|grandVoyageurPlus}) avec statut NOT NULL ``` L'attribut `regulier` est retrouvé comme méthode, il prend la valeur `True` dès que `num_carte` n'est pas nul dans la table `Voyageur`. ### Billet ``` Billet(#id:int, gare_depart:string, depart:heure, gare_arrivee:string, arrivee:heure, assurance:bool, prix:int, voyageur=>Voyageur) ``` * id $\rightarrow$ gare_depart, depart, gare_arrivee, arrivee, assurance, prix DF triviale car id est une clé artificielle * (assurance, gare_depart, gare_arrivee, depart, arrivee) $\rightarrow$ prix La souscription à l'assurance nécessite un coût supplémentaire ce qui élève le prix du trajet. * (prix, gare_depart, gare_arrivee, depart, arrivee) $\rightarrow$ assurance En connaissant le prix d'un trajet sans assurance, il est possible de déterminer si un billet contient l'assurance du trajet. La relation est en **1 NF** car tous ses attributs sont atomiques et elle possède une clé `id`. La relation est en **2 NF** car la seule clé candidate `id` n'est composée que d'un attribut, aucun attribut ne peut dépendre que d’une partie de la clé. La relation n'est pas en **3 NF** car les attributs prix, assurance, arrivee, depart sont non clés et dépendent d'attributs non clés. Passage en **3NF** : ``` Billet(#id, gare_depart => Deplacement.gare_depart, gare_arrivee => Deplacement.gare_arrivee, arrivee => Deplacement.arrivee, depart => Deplacement.depart, assurance => Deplacement.assurance) Deplacement (#gare_depart, #gare_arrivee, #arrivee, #depart, #assurance, prix) ``` ### Train ``` Train(#num:int, placemax:const int, classe1:const bool, vitessemax:const int, type:{RER|TER|TGV}, code_ligne=>ligne) ``` * num $\rightarrow$ placemax, classe1, vitessemax, type, code_ligne * type $\rightarrow$ placemax, classe1, vitessemax, En considérant notre modèle (avec des vitesses max différentes pour chacun des 3 types de train gérés) : * vitessemax $\rightarrow$ type, placemax, classe1, * placemax $\rightarrow$ type, vitessemax, classe1, La relation est en **1NF**, elle possède une clé (num) et tous ses attributs sont atomiques. La relation est en **2NF** car sa clé ne possède qu'un seul élément (num). La relation n'est pas en **3NF** car les attributs type, vitessemax, classe1 et placemax dépendent d'attributs n'appartenant à aucune clé candidate. Passage en **3NF** ``` Train(#num, code_ligne=>Ligne, type=>TypeTrain.type) TypeTrain(#type, vitessemax=>Vitesse.vitessemax) Vitesse(#vitessemax, placemax=>Place.placemax) Place(#Placemax, classe1) ``` ### Gare ```Gare(#nom:string, #ville:string, adresse:string, horaire:heure)``` **Remarque**:`horaire` signifie fuseau horaire. Le fuseau horaire de la gare dépend de l'emplacement de celle-ci et donc de sa ville. * (nom, ville) $\rightarrow$ adresse * ville $\rightarrow$ horaire La Relation est en **1NF** : possède une clé (nom, ville) et tous les attributs sont atomiques. La relation n'est pas en **2NF** (et necessairement pas en **3NF**) car `horaire` (n'appartenant pas à la clé) dépend d'une partie de la clé (ville est une partie de la clé). Passage en **2NF** : ``` Gare(#nom, #ville=>Ville, adresse) Ville(#ville, horaire) ``` On remarque que ce schéma est en **2NF** (puisque `horaire` dépend maintenant fonctionnellement d'une clé et non plus d'une partie de clé). La relation est en **3NF** : elle est en **2NF** et les attributs n'appartenant à aucun clé candidate (`horaire` et `ville`) dépendent directement de clés candidates ### Trajet ``` Trajet(#place: int, #id=>Billet, #horaire_depart => Horaire.id, #horaire_arrivee => Horaire.id) ``` Cette relation est nécessairement une relation toute clé car aucun attribut ne suffit à déterminer les autres. En effet, horaire de départ et horaire d'arrivée ne suffisent à déduire ni la place ni le billet, car plusieurs billets peuvent être liés à un trajet effectués d'un même départ à une même arrivée, et ce à des places différentes. La place et l'id du billet ne suffisent pas non plus puisque sur un même billet, plusieurs trajets différents peuvent être présents. Tous les attributs sont nécessaires pour constituer la clé du trajet. D'où l'on déduit que la classe est déjà en 3NF.