Archives par étiquette : clé primaire

Les formes normales

Relation, es-tu bien normale ?

Le but de la normalisation d’un schéma de base de données relationnelle ? Principalement l’élimination de la redondance et l’assurance d’avoir des données cohérentes (pas la même adresse orthographiée de N façons différentes, par exemple). Je dis « de la redondance inutile » car même si cela semble un pléonasme, il existe des cas où elle peut avoir une utilité et notamment quand la rapidité des accès aux données est placée au centre des préoccupations du concepteur.

normaliser

Normalisez avant qu’il ne faille tout jeter !

Les formes normales, des règles à suivre pour rester en forme !

Les formes normales sont des règles à suivre pour parvenir à éliminer cette redondance inutile. Nous n’irons pas en détail dans les aspects formels de ces formes normales, parce qu’ils ne sont pas indispensables à la compréhension de celles-ci et parce qu’ils rebutent inutilement le débutant. Sim-pli-ci-té !

1NF

Que nous dit cette première forme normale (1st Normal Form) ? Elle nous dit que tout attribut d’une relation (toute colonne d’une table, si vous préférez) ne doit posséder qu’une valeur pour chacun de ses enregistrements (ou tuples).

Plus concrètement, voici une table enseignant qui viole allégrement 1NF :

Table violant 1NF

La colonne prenom contient deux valeurs, cette colonne n’est donc pas mono-valuée comme nous l’impose 1NF mais multi-valuée, on dit que prenom ne contient pas de valeur atomique, que c’est un groupe de valeurs.

Comment se mettre en conformité avec 1NF ?

Dans notre cas ici, il ne faut pas faire l’économie d’une colonne dédiée au deuxième prénom (il pourrait même y en avoir un troisième, voire N car « le nombre de prénoms qui peuvent être attribués par les parents à un même enfant n’est pas fixé par la loi » nous dit le site Service Public). Créons donc cette nouvelle colonne et notons que la création de celle-ci nous permettra de faire des recherches de meilleure qualité sur les prénoms, par exemple en utilisant un index !

Table en conformité avec 1NF

Plutôt simple, n’est-ce pas ? Que dire de cette relation :

Table violant 1NF

Encore une fois, notre colonne adresse est multi-valuée ! Même si elle ne contient qu’une seule adresse, cette adresse elle-même contient plusieurs informations, de nature différente: un nom de rue, un numéro dans cette rue, un code postal, un nom de ville…Pourquoi ne pas créer une table adresse avec un champ numero, type_voie (rue, avenue, boulevard etc.), code_postal, ville etc. ? Cela peut servir si l’on veut normaliser nos adresses grâce à des outils tierce-partie et les rendre « propres ». Parfois il arrive que l’on laisse volontairement l’adresse dans cet état pour minimiser les jointures et donc accéder le plus rapidement possible à l’information…A vous d’étudier la pertinence de chacune de ces façons de faire : gardez simplement à l’esprit que l’absence de normalisation peut coûter cher plus tard…quand les données auront enflé !

2NF

Tout d’abord, pour être en 2NF, il faut être en 1NF : on ne peut pas être sans avoir été, lorsque l’on normalise ! Pour évoquer 2NF, il nous faut parler des dépendances fonctionnelles ! Qu’est-ce qu’une DF ? Rien de bien compliqué, regardons de plus près cette relation enseigne :

2nf

Nous avons ici une clé primaire composée du couple (identifiant_enseignant, identifiant_cours). Notre colonne ville nous dit dans quelle ville a lieu le cours.
Nous voyons que la colonne ville dépend de identifiant_cours : le cours 1 est toujours donné à Avignon et le 2, toujours à Aix.

On dit ici que identifiant_cours détermine ville ou bien, dans le sens inverse, que ville dépend fonctionnellement de identifiant_cours.

Si pour des valeurs identiques d’une colonne C on a les mêmes valeurs dans la colonne C2, alors C détermine C2 et nous le noterons C → C2.

Ici, pour la valeur 1 dans la colonne identifiant_cours nous avons toujours la valeur Avignon en face et pour la valeur 2 dans la colonne identifiant_cours nous avons toujours la valeur Aix. Ce n’est pas le cas de identifiant_enseignant, qui n’a pas les mêmes valeurs de ville en face (regardez l’enseignant 1, il enseigne dans la ville d’Aix et dans la ville d’Avignon).

Dans notre relation enseigne nous distinguons:

  • des attributs (des colonnes, c’est pareil) qui forment une clé primaire
  • un attribut non clé (ville)

Ici nous avons identifié une dépendance fonctionnelle entre une partie de la clé (la colonne identifiant_cours) et une colonne non clé (ville). Voilà pourquoi cette relation viole 2NF.

Pour qu’une relation soit conforme à 2NF, les attributs non clé de cette relation doivent dépendre fonctionnellement de toute la clé et non d’une partie seulement

Ici nous avions : identifiant_cours → ville. La colonne identifiant_cours est une partie (la moitié pour être parfaitement exact) de la clé. CQFD.

Comment se mettre en conformité avec 2NF ?

Nous allons isoler la DF identifiant_cours → ville qui nous pose problème dans sa propre table, que nous pourrions appeler cours par exemple :

2nf-bis

Vous noterez que nous avons mis fin à la redondance inutile jusqu’alors présente dans la table (la ville potentiellement répétée N fois); cela nous aide aussi à assurer comme je vous l’ai dit en introduction la cohérence des données (que se serait-il passé avant si nous avions écrit Avignon « Avinion », « Avignom » et « Avignon » ? Nous aurions eu trois villes différentes !). Dorénavant, Avignon figure une fois et une seule…et le nom est écrit comme il faut.

Que va devenir notre ancienne relation ? Eh bien oui, nous l’avons quelque peu rabotée !

2nf3

Nous avons sorti ville mais il nous faut bien garder le lien entre le cours et la ville, voilà pourquoi la source de la DF identifiant_cours → ville, c’est à dire identifiant_cours, RESTE dans la table d’origine. Grâce à identifiant_cours, qui existe maintenant dans les deux tables, nous pouvons effectuer des jointures et ainsi garantir qu’on a maintenu l’information initiale qui était « tel cours se donne dans telle ville ».

En pratique ici, identifiant_cours sera clé primaire dans la nouvelle table cours et une contrainte d’intégrité référentielle partira depuis identifiant_cours situé dans enseigne vers identifiant_cours situé dans cours.

3NF

Tout comme il nous faut être en 1NF pour être en 2NF, il nous faut être en 2NF pour être en 3NF : nous procédons de manière incrémentale !

Pour être en 3NF, il faut que toute colonne non clé ne dépende que de la clé de la relation

Revenons un instant à nos enseignants, dont la structure a quelque peu évolué :

3nf

Nous avons souhaité pour chaque enseignant dire à quel département il était rattaché et où ce dernier se situait. Dans le cas présent, localisation dépend de departement (noté departement → localisation). Notre attribut departement ne fait pas partie de la clé, pas plus que localisation, dont il dépend. Voilà pourquoi cette relation n’est pas conforme à 3NF !

Les problèmes posés par cet exemple sont les mêmes que pour la 2NF, à savoir :

  • la localisation du département est répétée dans chaque enregistrement (regardez les deux premiers) et elle peut aussi être orthographiée différemment suite à une erreur de saisie, compromettant ainsi la cohérence des données et donc leur qualité
  • si la localisation du département change, il faut mettre à jour tous les enseignants qui y travaillent
  • Si le département n’a plus d’enseignant, nous perdons l’information de sa localisation

Comment se mettre en conformité avec 3NF ?

Comme pour 2NF, il va nous falloir isoler la DF anormale departement → localisation dans sa propre table, comme ceci :

3nf2

Là encore vous noterez que nous avons mis fin à la redondance qui jusque là existait dans notre table. Notre relation enseignant va « maigrir » elle aussi mais on doit également y faire exister un lien vers notre nouvelle relation, ce lien ce sera la colonne identifiant_departement :

3nf3

Conclusion

Nous entretenons désormais des relations tout à fait normales !

En réalité, il existe d’autres formes normales après 3NF, mais quand on a normalisé en 3NF, on a déjà éliminé la grande partie de ces vilaines redondances que nous voulons éviter.

Pour retenir facilement 2NF et 3NF, les gens qui travaillent sur les bases de données connaissent par cœur cette phrase de feu William Kent :

« The key, the whole key, and nothing but the key »

qui reprend de façon assez humoristique le serment que font les témoins devant un tribunal : « Je jure de dire la vérité, toute la vérité, rien que la vérité » (des petits malins on rajouté « So help me Codd » – E.F Codd étant considéré comme le père des bases de données relationnelles – pour remplacer le « so help me God » (Dieu me vienne en aide) qui termine la phrase aux Etats-Unis).

En effet :

  • En 2NF, tout attribut (ou colonne) non clé doit dépendre de la clé toute entière (the whole key)
  • En 3NF, tout attribut (ou colonne) non clé ne doit dépendre QUE de la clé (nothing but the key)

Vous voilà maintenant armés pour partir à l’assaut de vos tables et les normaliser ! Bon courage !