Je suis tombé sur un problème de conception de base de données hors de ma ligue et mon gourou DBA est en train de faire des exercices d'incendie.
En substance, j'ai une table avec la clé primaire suivante (PK pour la brièveté):
child_id integer
parent_id integer
date datetime
child_id
et parent_id
sont des clés étrangères aux tables d'entités. La table "enfant" elle-même contient également une clé étrangère vers la table "parent", et lo, chacune fait child_id
toujours référence à la même chose parent_id
que prévu par le tableau ci-dessus. En fait, il se trouve qu'il y a du code supplémentaire qui maintient les deux synchronisés.
Ce qui fait dire à ce novice trop enthousiaste de la normalisation: «Je devrais plutôt supprimer la redondance!
Je me décompose comme suit:
Table_1 PK:
child_id integer
date datetime
Table_2 PK:
parent_id integer
date datetime
Table_3: (already exists)
child_id integer PRIMARY KEY
parent_id integer FOREIGN KEY
Et voilà, quand je rejoins ces gars ensemble de façon naturelle, je récupère la table d'origine. C'est ma compréhension qui fait ce 5NF.
Cependant, maintenant je me rends compte qu'il existe une règle commerciale cachée.
Normalement, les dates associées à un donné child_id
doivent être un sous-ensemble des dates associées au correspondant parent_id
. Vous pouvez voir que le premier tableau applique cette règle.
Ma décomposition n'applique pas la règle, car vous pouvez ajouter librement au tableau 1 jusqu'à ce que les dates deviennent trop grandes.
Ce qui m'amène ici, avec les questions suivantes:
Cette décomposition est-elle 5NF? Bien que je dirais qu'il permet des anomalies d'insertion, il semble également suivre l'exemple du wiki, qui suit lui-même ce guide . L'expression ( je souligne) "nous pouvons reconstruire tous les faits réels à partir d'une forme normalisée composée de trois types d'enregistrement distincts" me donne une pause spéciale, car peu importe la quantité de déchets dans lesquels je pompe
Table_1
, la jointure naturelle l'ignore toujours.Supposons que je n'aime pas cette décomposition (je n'aime pas). Je reconnais librement que la solution pratique est de laisser la table et le code tels quels. Mais, en théorie, existe-t-il un moyen de décomposer et / ou d'ajouter des contraintes pour que je m'éloigne de la première table et préserve mes règles métier?
Réponses:
La normalisation est basée sur des dépendances fonctionnelles. Les dépendances fonctionnelles ont à voir avec la sémantique; ils ont à voir avec ce que les données des moyens . Lorsque vous simplifiez un problème du monde réel au niveau de "parent_id, child_id, date" et que vous n'incluez aucun exemple de données, vous limitez vraiment l'aide qu'un concepteur de base de données consciencieux peut vous apporter.
Le fait que vous ayez une clé {child_id, parent_id, date} dans une table et que vous ayez (il semble) une paire unique {child_id, parent_id} dans la table enfant ne signifie pas nécessairement qu'une partie de la combinaison est redondante . Cela peut signifier que dans la table qui a {child_id, parent_id, date} comme clé primaire, la paire d'attributs {child_id, parent_id} doit référencer la table enfant en premier lieu.
Si tel est le cas, vous pouvez utiliser
FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)
. Pour ce faire, vous avez besoin d'une contrainte UNIQUE sur la paire de colonnes (child_id, parent_id) dans la table "child", ce qui ne devrait pas être un problème si child_id est sa clé primaire.Mais il n'y a aucun moyen de savoir sans savoir ce que signifient les données, et vous êtes le seul dans ce fil qui le sait. (Mais nous serions heureux de vous laisser nous l'expliquer.)
En ce qui concerne la table d'origine, vous semblez dire que child_id -> parent_id. Si tel est le cas, pourquoi parent_id dans la table d'origine en premier lieu? Pourquoi la clé n'est-elle pas juste (child_id, date), avec une référence de clé étrangère à la table "enfant"? Il me semble que le type de redondance dont vous parlez pourrait être résolu en supprimant la colonne "parent_id".
Le DDL SQL et des exemples de données sous forme d'instructions INSERT nous aident à vous aider. Les instructions DDL et INSERT sont plus précises que les descriptions.
la source
Essaye ça...
(child_id,parent_id)
la table enfant(PK,FK:child_id, PK,FK:parent_id, PK:date)
reste telle quelle, le FK est sur 2 colonnes à la nouvelle contrainte uniqueou
(PK,FK:child_id, FK:parent_id)
1: 1 avec enfant(PK,FK: child_id, PK,FK: parent_id, PK:date)
reste telle quelle. mais le FK est sur 2 colonnes vers la nouvelle tableSi rien d'autre, cela peut vous inspirer ...
Si j'ai bien compris, cela supprimera la redondance et le code ...
la source