Normaliser une Base de Données sans Perdre le Sens Métier
Bases de données & persistanceUtilisation des dépendances fonctionnelles pour éliminer les anomalies tout en préservant les instantanés historiques dans les factures de réparation.
Dans cet article
Le Danger de la Redondance
Lorsqu’une table stocke plusieurs faits distincts dans une seule ligne, elle génère des anomalies de mise à jour, d’insertion et de suppression. Prenons une table FactureReparation contenant : IDFacture, IDClient, TelClient, IDPiece, NomFournisseur, TelFournisseur et PrixFacturé.
Dans cette structure, le TelClient dépend uniquement de l’ IDClient, et le TelFournisseur dépend uniquement de l’ IDPiece (en supposant un fournisseur par pièce). Ce sont des dépendances fonctionnelles. Comme ces informations sont répétées à chaque facture, nous rencontrons trois risques :
- Anomalie de Mise à Jour : Si un client change de numéro, il faut modifier chaque facture historique. Un oubli crée une incohérence des données.
- Anomalie d’Insertion : Impossible d’enregistrer les coordonnées d’un nouveau fournisseur tant qu’on n’a pas vendu une de ses pièces sur une facture.
- Anomalie de Suppression : Supprimer la seule facture contenant une pièce spécifique entraîne la perte totale des coordonnées du fournisseur.
Distinguer l’État de l’Historique
Une erreur courante lors de la normalisation est de supprimer des données qui semblent redondantes mais sont en réalité des instantanés (snapshots) historiques.
Dans notre scénario, le PrixFacturé semble dépendre de l’ IDPiece. Cependant, les prix évoluent. Si vous déplacez le prix vers une table Pieces et le supprimez de la LigneFacture, modifier le prix aujourd’hui modifiera rétroactivement le total d’une facture d’il y a trois ans. C’est une perte de sens métier.
- Données Dynamiques : Le téléphone du client (état actuel).
- Données Snapshot : Le prix au moment de la vente (fait historique).
Solution Travaillée : Le Plan de Normalisation
Pour résoudre les anomalies tout en préservant le prix, nous décomposons la table selon les dépendances fonctionnelles.
1. Identification des Dépendances
IDFacture→IDClient,DateFactureIDClient→TelClientIDPiece→IDFournisseur,NomPieceIDFournisseur→NomFournisseur,TelFournisseur(IDFacture, IDPiece)→PrixFacturé(Le prix est lié à la transaction, pas seulement à la pièce).
2. Schéma Résultant (Modèle Logique)
- Clients : (
IDClient[PK],TelClient) - Fournisseurs : (
IDFournisseur[PK],NomFournisseur,TelFournisseur) - Pieces : (
IDPiece[PK],NomPiece,IDFournisseur[FK]) - Factures : (
IDFacture[PK],IDClient[FK],DateFacture) - LignesFacture : (
IDFacture[FK],IDPiece[FK],PrixFacturé) → PK Composite (IDFacture,IDPiece)
3. Analyse du Résultat
En séparant les tables, nous traitons les anomalies :
- Mise à jour : On change le téléphone une seule fois dans la table
Clients. - Insertion : On ajoute un fournisseur sans avoir besoin de facture.
- Suppression : On supprime une ligne de facture sans perdre l’existence du fournisseur.
- Intégrité : Le
PrixFacturéreste dansLignesFacture, garantissant que les archives sont immuables malgré les hausses de prix futures.
Exercice
Scénario : Vous avez une table AffectationProjet : IDProjet, NomProjet, IDEmploye, NomEmploye, Role, et TauxHoraire. Le TauxHoraire est négocié spécifiquement pour cette affectation, et non le salaire général de l’employé.
Tâche : Identifiez les dépendances fonctionnelles et précisez quels champs doivent rester dans l’entité de jointure pour ne pas perdre le sens métier.
Réponse :
- Dépendances :
IDProjet→NomProjet;IDEmploye→NomEmploye. - Le
Roleet leTauxHorairedépendent de la combinaison(IDProjet, IDEmploye). - Pour préserver le sens métier, le
TauxHorairedoit rester dans l’entité de jointureAffectationProjetcar c’est un snapshot de l’accord pour ce projet précis, et non un attribut global de l’employé.
La clé de ligne suppose une occurrence de chaque pièce par facture ; utilisez un identifiant de ligne distinct si une pièce peut apparaître à plusieurs prix. Le prix facturé conserve son sens indépendamment du catalogue, sans rendre techniquement la ligne immuable. Contrôlez séparément les modifications de l’historique.