© Your Copyright
La modélisation des bars qui servent des bières peut être décrite simplement dans une seule table :
- \(barsdumonde(\underline{id\_bar,id\_biere},bar,pays,continent,biere,couleur,origine,stock)\)
en partant du fait qu’il faudra connaître un numéro de bar (id_bar
) et de bière (id_biere
)
pour retrouver toutes les informations sur une bière servie dans un bar.
En effet il ne suffit pas de connaître le nom du bar
et celui de la biere
sachant que :
- plusieurs bars peuvent avoir le même nom (il peut exister plusieurs
bar='Bar du Coin'
)- un même nom peut être donné à une bière produite dans différents pays (ex : “Budweiser” produite en “Tchéquie” et aux “USA”)
Partant de cette modélisation de base non normalisée, on structurera notre modèle de données en se basant sur les trois premières formes normales et en appliquant le théorème de Heath pour proposer une décomposition sans perte à chaque étape de normalisation.
En partant de notre première structuration des informations dans une seule table nous souhaiterions obtenir la représentation suivante des informations :
barsdumonde | ||||||||
---|---|---|---|---|---|---|---|---|
id_bar | bar | pays | continent | id_biere | biere | couleur | origine | stock |
1 | Bar du Coin | France | Europe | 1 | Kronenbourg | Blonde | France | 1000 |
2 | Guinness | Brune | Irlande | 250 | ||||
3 | Spaten | Blonde | Allemagne | 50 | ||||
4 | Bush | Blonde | Belgique | 100 | ||||
2 | Cafe der Ecke | Allemagne | Europe | 3 | Spaten | Blonde | Allemagne | 5000 |
5 | Erdinger | Blonde | Allemagne | 30000 | ||||
6 | Budweiser | Blonde | Tchéquie | 7500 | ||||
3 | Corners Pub | USA | Amérique | 6 | Budweiser | Blonde | Tchéquie | 10 |
7 | Budweiser | Blonde | USA | 10000 | ||||
4 | Bush | Blonde | Belgique | 2500 |
Avec cette représentation, quel serait le résultat de la requête SQL suivante :
SELECT * FROM barsdumonde
WHERE bar='Bar du Coin';
Est-il possible de retrouver facilement les bières servies au “Bar du Coin” ?
Cette modélisation ne permet donc pas de manipuler facilement les informations.
Cette représentation de l’information contredit la première forme normale (1NF) :
- tous les attributs de la relation doivent avoir des valeurs simples (contiennent une valeur atomique)
On doit donc dupliquer toutes les informations regroupées par bar.
NB : Ce genre de regroupement pourra toujours être réalisé ultérieurement (GROUP BY
)
La représentation de notre premier modèle de données en 1NF sera donc :
barsdumonde | ||||||||
---|---|---|---|---|---|---|---|---|
id_bar | id_biere | bar | pays | continent | biere | couleur | origine | stock |
1 | 1 | Bar du Coin | France | Europe | Kronenbourg | Blonde | France | 1000 |
1 | 2 | Bar du Coin | France | Europe | Guinness | Brune | Irlande | 250 |
1 | 3 | Bar du Coin | France | Europe | Spaten | Blonde | Allemagne | 50 |
1 | 4 | Bar du Coin | France | Europe | Bush | Blonde | Belgique | 100 |
2 | 3 | Cafe der Ecke | Allemagne | Europe | Spaten | Blonde | Allemagne | 5000 |
2 | 5 | Cafe der Ecke | Allemagne | Europe | Erdinger | Blonde | Allemagne | 30000 |
2 | 6 | Cafe der Ecke | Allemagne | Europe | Budweiser | Blonde | Tchéquie | 7500 |
3 | 6 | Corners Pub | USA | Amérique | Budweiser | Blonde | Tchéquie | 10 |
3 | 7 | Corners Pub | USA | Amérique | Budweiser | Blonde | USA | 10000 |
3 | 4 | Corners Pub | USA | Amérique | Bush | Blonde | Belgique | 2500 |
Cependant du fait de la duplication de l’information concernant les bars à chaque bière qu’ils servent, cette modélisation présente de nombreux inconvénients :
duplication de l’information concernant les bars pour chaque bière qu’ils servent.
anomalie d’insertion :
si on veut insérer une nouvelle bière il faudra l’associer à un bar (
id_bar
).INSERT INTO barsdumonde VALUES(4,8,NULL,NULL,NULL,'Pilsner Urquell','Blonde','Tchéquie',NULL); -- ou INSERT INTO barsdumonde VALUES(4,8,'Bar des Amis','France','Europe','Pilsner Urquell','Blonde','Tchéquie',NULL); -- ou INSERT INTO barsdumonde VALUES(1,8,'Bar du Coin','France','Europe','Pilsner Urquell','Blonde','Tchéquie',1250);anomalie de mises à jour :
rebaptiser la
'Budweiser'
produite en''Tchéquie'
en'Budwar'
implique de parcourir tous les éléments de l’ensemble pour faire la mise à jour :UPDATE barsdumonde SET biere='Budwar' WHERE biere='Budweiser' AND origine='Tchéquie' -- ou UPDATE barsdumonde SET biere='Budwar' WHERE id_biere IN ( SELECT id_biere FROM barsdumonde WHERE biere='Budweiser' AND origine='Tchéquie' );anomalie de suppression :
enlever le
'Bar du Coin'
de l’ensemble implique de perdre toute l’information sur les bières qu’il servait.DELETE FROM barsdumonde WHERE bar='Bar du Coin';
Tests d’anomalies sur la base en 1NF :
Il faut donc structurer la base de données de manière à répartir les informations concernant les bars et les bières dans différents ensembles.
Cependant à partir de la répartition de l’information dans ces nouveaux ensembles, il faudra pouvoir reconstituer les informations présentes dans le modèle initial.
Pour mieux structurer notre modèle en 1NF on doit vérifier s’il respecte la deuxième forme normale (2NF) :
- il n’existe pas de partie de clé (sous-clé) qui soit une clé pour un attribut non-clé
Autrement dit : Toute la clé est nécessaire
Dans notre modèle d’origine :
- \(barsdumonde(\underline{id\_bar,id\_biere},bar,pays,continent,biere,couleur,origine,stock)\)
La clé de la relation est constitué des attributs : id_bar,id_biere
Or le numéro du bar suffit à retrouver les informations sur le bar.
- \(id\_bar \rightarrow bar,pays,continent\)
On peut donc décomposer notre relation de départ en appliquant le théorème de Heath :
- \(barsdumonde(\underline{id\_bar},bar,pays,continent)\)
- \(bieresdumonde(\underline{id\_bar,id\_biere},biere,couleur,origine,stock)\)
barsdumonde | |||
---|---|---|---|
id_bar | bar | pays | continent |
1 | Bar du Coin | France | Europe |
2 | Cafe der Ecke | Allemagne | Europe |
3 | Corners Pub | USA | Amérique du Nord |
bieresdumonde | |||||
---|---|---|---|---|---|
id_bar | id_biere | biere | couleur | origine | stock |
1 | 1 | Kronenbourg | Blonde | France | 1000 |
1 | 2 | Guinness | Brune | Irlande | 250 |
1 | 3 | Spaten | Blonde | Allemagne | 50 |
1 | 4 | Bush | Blonde | Belgique | 100 |
2 | 3 | Spaten | Blonde | Allemagne | 5000 |
2 | 5 | Erdinger | Blonde | Allemagne | 30000 |
2 | 6 | Budweiser | Blonde | Tchéquie | 7500 |
3 | 6 | Budweiser | Blonde | Tchéquie | 10 |
3 | 7 | Budweiser | Blonde | Etats-Unis | 10000 |
3 | 4 | Bush | Blonde | Belgique | 2500 |
Cependant notre structuration n’est pas encore en 2NF.
En effet il n’y a pas besoin de connaître le numéro du bar pour retrouver les informations sur une bière.
- \(id\_biere \rightarrow biere,couleur,origine\)
On peut donc à nouveau décomposer notre relation bieresdumonde
en appliquant le théorème de Heath :
- \(bieresdumonde(\underline{id\_biere},biere,couleur,origine)\)
- \(services(\underline{id\_bar,id\_biere},stock)\)
barsdumonde | |||
---|---|---|---|
id_bar | bar | pays | continent |
1 | Bar du Coin | France | Europe |
2 | Cafe der Ecke | Allemagne | Europe |
3 | Corners Pub | USA | Amérique du Nord |
bieresdumonde | |||
---|---|---|---|
id_biere | biere | couleur | origine |
1 | Kronenbourg | Blonde | France |
2 | Guinness | Brune | Irlande |
3 | Spaten | Blonde | Allemagne |
4 | Bush | Blonde | Belgique |
5 | Spaten | Blonde | Allemagne |
6 | Erdinger | Blonde | Allemagne |
7 | Budweiser | Blonde | Tchéquie |
8 | Budweiser | Blonde | Etats-Unis |
services | ||
---|---|---|
id_bar | id_biere | stock |
1 | 1 | 1000 |
1 | 2 | 250 |
1 | 3 | 50 |
1 | 4 | 100 |
2 | 3 | 5000 |
2 | 5 | 30000 |
2 | 6 | 7500 |
3 | 6 | 10 |
3 | 7 | 10000 |
3 | 4 | 2500 |
Cette structuration permet d’éliminer de la redondance d’information et de retrouver les informations initiales par jointure naturelle :
- \(\Join_{[services.id\_biere=bieresdumonde.id\_biere]}(bieresdumonde,\Join_{[services.id\_bar=barsdumonde.id\_bar]}(services,bars))\)
Il subsiste toujours de la redondance d’information dans notre modèle de données en 2NF du fait qu’à chaque fois que l’on insère
un bar dans un pays il est nécessaire de renseigner l’information sur le continent où se trouve ce pays.
Or, il existe une dépendance fonctionnelle entre les informations pays,continent
:
- \(pays \rightarrow continent\)
qui représente donc une dépendance transitive entre ces attributs non-primitifs.
On doit respecter la troisème forme normale (3F) :
- la relation est en deuxième forme normale (2NF) et tous les attributs non-primitifs sont directement dépendant d’une clé
Autrement dit :
- il n’existe pas de dépendances fonctionnelles entre les attributs non-clé.
On peut donc à nouveau décomposer notre relation barsdumonde
en appliquant le théorème de Heath :
- \(bars(\underline{id\_bar},nom,pays)\)
- \(monde(\underline{pays},continent)\)
On obtient au final une structuration de notre base de donnée en 3NF :
- \(monde(\underline{pays},continent)\)
- \(bars(\underline{id\_bar},nom,pays)\)
- \(bieres(\underline{id\_biere},biere,couleur,origine)\)
- \(services(\underline{id\_bar,id\_biere},stock)\)
monde | |
---|---|
pays | continent |
France | Europe |
Allemagne | Europe |
USA | Amérique |
bars | ||
---|---|---|
id_bar | bar | pays |
1 | Bar du Coin | France |
2 | Cafe der Ecke | Allemagne |
3 | Corners Pub | USA |
bieres | |||
---|---|---|---|
id_biere | biere | couleur | origine |
1 | Kronenbourg | Blonde | France |
2 | Guinness | Brune | Irlande |
3 | Spaten | Blonde | Allemagne |
4 | Bush | Blonde | Belgique |
5 | Spaten | Blonde | Allemagne |
6 | Erdinger | Blonde | Allemagne |
7 | Budweiser | Blonde | Tchéquie |
8 | Budweiser | Blonde | Etats-Unis |
services | ||
---|---|---|
id_bar | id_biere | stock |
1 | 1 | 1000 |
1 | 2 | 250 |
1 | 3 | 50 |
1 | 4 | 100 |
2 | 3 | 5000 |
2 | 5 | 30000 |
2 | 6 | 7500 |
3 | 6 | 10 |
3 | 7 | 10000 |
3 | 4 | 2500 |
On obtient bien par jointure naturelle :
- \(\Join(monde,\Join(bars,\Join(services,bieres)))\)
les informations présentes dans la base de données initiale en 1NF :
barsdumonde | ||||||||
---|---|---|---|---|---|---|---|---|
id_bar | id_biere | bar | pays | continent | biere | couleur | origine | stock |
1 | 1 | Bar du Coin | France | Europe | Kronenbourg | Blonde | France | 1000 |
1 | 2 | Bar du Coin | France | Europe | Guinness | Brune | Irlande | 250 |
1 | 3 | Bar du Coin | France | Europe | Spaten | Blonde | Allemagne | 50 |
1 | 4 | Bar du Coin | France | Europe | Bush | Blonde | Belgique | 100 |
2 | 3 | Cafe der Ecke | Allemagne | Europe | Spaten | Blonde | Allemagne | 5000 |
2 | 5 | Cafe der Ecke | Allemagne | Europe | Erdinger | Blonde | Allemagne | 30000 |
2 | 6 | Cafe der Ecke | Allemagne | Europe | Budweiser | Blonde | Tchéquie | 7500 |
3 | 6 | Corners Pub | USA | Amérique | Budweiser | Blonde | Tchéquie | 10 |
3 | 7 | Corners Pub | USA | Amérique | Budweiser | Blonde | USA | 10000 |
3 | 4 | Corners Pub | USA | Amérique | Bush | Blonde | Belgique | 2500 |