Tables supplémentaires ou clés étrangères non spécifiques ?
-
09-06-2019 - |
Question
Il existe plusieurs types d'objets dans un système, et chacun possède sa propre table dans la base de données.Un utilisateur devrait pouvoir commenter n’importe lequel d’entre eux.Comment concevriez-vous le(s) tableau(s) de commentaires ?Je peux penser à quelques options :
- Une table de commentaires, avec une colonne FK pour chaque type d'objet (ObjectAID, ObjectBID, etc.)
- Plusieurs tables de commentaires, une pour chaque type d'objet (ObjectAComments, ObjectBComments, etc.)
- Un FK générique (ParentObjectID) avec une autre colonne pour indiquer le type ("ObjectA")
Lequel choisiriez-vous?Existe-t-il une meilleure méthode à laquelle je ne pense pas ?
La solution
@palmsey
À peu près, mais la variation de ce modèle que j'ai vue le plus souvent élimine ObjectAID
et coll. ParentID
devient à la fois le PK et le FK pour Parents
.Cela vous donne quelque chose comme :
Parents
ParentID
ObjectA
ParentID
(FK et PK)ColumnFromA NOT NULL
ObjectB
ParentID
(FK et PK)ColumnFromB NOT NULL
Comments
resterait le même.Ensuite, il vous suffit de limiter la génération d'ID afin de ne pas vous retrouver accidentellement avec un ObjectA
rangée et un ObjectB
ligne qui pointe toutes les deux vers la même Parents
rangée;le moyen le plus simple de le faire est d'utiliser la même séquence (ou autre) que celle que vous utilisez pour Parents
pour ObjectA
et ObjectB
.
Vous voyez également beaucoup de schémas avec quelque chose comme :
Parents
ID
SubclassDiscriminator
ColumnFromA (nullable)
ColumnFromB (nullable)
et Comments
resterait inchangé.Mais maintenant, vous ne pouvez plus appliquer toutes vos contraintes métier (les propriétés des sous-classes sont toutes nullables) sans écrire de déclencheurs ou sans le faire sur une couche différente.
Autres conseils
Est-il possible de concevoir le schéma de manière à ce que les tables commentables (faute d'un meilleur mot) suivent l'un des modèles standard de modélisation de l'héritage ?Si tel est le cas, vous pouvez faire en sorte que le FK de la table de commentaires pointe vers la table parent commune.
@Hank Gay
Donc quelque chose comme :
- ObjetA
- ObjetAID
- IDParent
- ObjetB
- ObjetBID
- IDParent
- commentaires
- ID du commentaire
- IDParent
- Parents
- IDParent
Soyez prudent avec les clés étrangères génériques qui ne pointent pas exactement vers une seule table.Les performances des requêtes souffrent considérablement si vous devez diviser la condition Where sur un type et pointer vers plusieurs tables différentes.Si vous n'avez que quelques types et que le nombre de types n'augmentera pas, il est possible d'avoir des clés étrangères nullables distinctes pour les différentes tables, mais si vous avez plus de types, il est préférable de proposer un modèle de données différent (comme suggestion de @palmsey).
L'une des choses que j'aime faire est d'avoir des tableaux séparés qui relient le tableau générique/commun à tous les tableaux individualisés.
Ainsi, pour les objets Foo et Bar puis les commentaires sur Foo & Bar, vous auriez quelque chose comme ceci :
- Fou
- ID Foo (PK)
- Bar
- ID de barre (PK)
- Commentaire
- ID du commentaire (PK)
- Texte du commentaire
- FooComment
- ID Foo (PK FK)
- ID du commentaire (PK FK)
- BarCommentaire
- ID de barre (PK FK)
- ID du commentaire (PK FK)
Cette structure :
- Vous permet d'avoir un tableau de commentaires commun
- Ne nécessite pas de base de données avec héritage de table
- Ne pollue pas les tables Foo et Bar avec des informations liées aux commentaires
- Vous permet de joindre un commentaire à plusieurs des objets (qui peuvent être désirables)
- Vous permet d'attacher d'autres propriétés à la jonction de Foo/Bar et Comment si vous le souhaitez.
- Préserve toujours les relations avec le standard (c'est-à-dire :rapide, simple, fiable) clés étrangères