J'ai des tonnes d'instances où je dois mettre en œuvre une sorte d'association polymorphe dans ma base de données. Je perds toujours des tonnes de temps de penser à travers toutes les options à nouveau. Voici les 3 que je peux penser. J'espère qu'il y a une meilleure pratique pour SQL Server.
Voici l'approche multiple de colonne
Voici l'approche clé étrangère
Et voici l'approche de la table de base
Les deux approches les plus courantes sont la table par classe (c.-à-d. Une table pour la classe de base et une autre table pour chaque sous-classe contenant les colonnes supplémentaires nécessaires pour décrire la sous-classe) et la table par hiérarchie (c'est-à-dire toutes les colonnes d'une table, avec une seule table. Colonnes pour permettre la discrimination des sous-classes. La meilleure approche dépend vraiment des détails de votre stratégie d'application et d'accès aux données.
Vous auriez une table par classe dans votre premier exemple en inversant la direction du FK et en supprimant les identifiants supplémentaires du parent. Les deux autres sont essentiellement des variantes de table par classe.
Un autre nom commun de ce modèle est le modèle SuperType, où l'on a un ensemble de base d'attributs pouvant être étendus via une adhésion à une autre entité. Dans Oracle Books, il est enseigné à la fois comme modèle logique et implémentation physique. Le modèle sans les relations permettrait aux données de croître dans des enregistrements d'État et d'orphelins non valides, je validerais vivement les besoins avant de sélectionner ce modèle. Le modèle supérieur avec la relation stockée dans l'objet de base provoquerait des nuls et dans un cas où les champs étaient mutuellement exclusives, vous auriez toujours une null. Le diagramme inférieur où la clé est appliquée dans l'objet enfant éliminerait les NULLS, mais rendrait également la dépendance une dépendance douce et permettre aux orphelins si la cascade n'était pas appliquée. Je pense que l'évaluation de ces traits vous aidera à choisir le modèle qui convient le mieux. J'ai utilisé les trois dans le passé.
J'ai utilisé la solution suivante pour résoudre un problème similaire:
Beaucoup de conception basée sur plusieurs: même si la relation est une 1 fois entre un objet et quelque chose, cela équivaut à une relation de nombreuses nombreuses personnes avec une modification du PK de la table de relation.
D'abord, je crée une table de relation entre un objet et quelque chose par objet, puis j'utilise la colonne Quelque_id en tant que PK.
C'est le DDL de la relation quelque chose-objet1 qui est la même pour objet2 et objet3 également:
CREATE TABLE Something
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Object1
(
ID INT PRIMARY KEY,
.....
)
CREATE TABLE Something_Object1
(
Something_ID INT PRIMARY KEY,
Object1_ID INT NOT NULL,
......
FOREIGN KEY (Something_ID) REFERENCES Something(ID),
FOREIGN KEY (Object1_ID) REFERENCES Object1(ID)
)
Plus de détails et des exemples d'autres options possibles dans ce billet touches multiples-étrangères-for-the même business-règle
J'ai utilisé ce que je suppose que vous appelleriez l'approche de la table de base. Par exemple, j'ai eu des tables pour des noms, des adresses et des phonumbers, chacun avec une identité comme pk. Ensuite, j'avais une entité de table d'entité principale (entitéïde) et une table de liaison: Attribut (Entitykey, AttributType, AttributTeKey), dans laquelle l'attributkey peut indiquer à l'une des trois premières tables, en fonction du documentTetype.
Quelques avantages: permettant autant de noms, d'adresses et de phonénumbers par entité comme nous, faciles à ajouter de nouveaux types d'attributs, une normalisation extrême, des attributs communs faciles à minoter (c'est-à-dire identifier des personnes en double), d'autres avantages de sécurité spécifiques à une entreprise
Inconvénients: des requêtes assez complexes pour construire des ensembles de résultats simples rendus difficile à gérer (c'est-à-dire que j'ai eu du mal à recruter des personnes avec suffisamment de côtelettes T-SQL); la performance est optimale pour des cas d'utilisation très spécifiques plutôt que par le général; L'optimisation des requêtes peut être délicate
Ayant vécu avec cette structure pendant plusieurs années de carrière beaucoup plus longue, j'hésiterais à l'utiliser à moins que j'aie eu les mêmes contraintes de logique de commerce et des mêmes modèles d'accès. Pour l'utilisation générale, je recommande vivement vos tables dactylographiées directement référence à vos entités. C'est-à-dire une entité (entité), nom (nom de nom, entitéïde, nom), téléphone (PhoneID, entitédid, téléphone), e-mail (courrier électronique, entitéidide, email). Vous aurez une répétition de données et des colonnes communes, mais il sera beaucoup plus facile de programmer et d'optimiser.
L'approche 1 est la meilleure mais l'association entre quelque chose et objet1, objet2, objet3 devrait être un à un.
Je veux dire que la table FK in Child (Object1, Object2, Object3) doit être une clé unique non nulle ou une clé primaire pour la table des enfants.
object1, Object2, Object3 peut avoir une valeur d'objet polymorphe.
Selon moi, votre premier type d'approche est la meilleure solution que vous puissiez définir les données ainsi que vos classes, mais que vos données primaires doivent être utilisées pour l'enfant.
Vous pouvez donc vérifier votre exigence et définir la base de données.
Approche 1 avec plusieurs colonnes Touches étrangères est la meilleure. Parce que cette façon, vous pouvez avoir des connexions prédéfinies avec d'autres tables et cela facilite la sélection des scripts de sélectionner, d'insérer et de mettre à jour des données.
Il n'y a pas de meilleure pratique simple ou universelle pour y parvenir. Tout dépend du type d'accès aux applications aura besoin.
Mon conseil serait de faire une vue d'ensemble sur le type d'accès attendu à ces tableaux:
Basé sur des réponses à ces questions, nous pourrions élaborer une solution appropriée.
Une possibilité supplémentaire de stocker des propriétés spécifiques aux sous-classes consiste à utiliser une table avec paires nom/valeur. Cette approche peut être particulièrement utile s'il existe un grand nombre de sous-classes différentes ou lorsque les champs spécifiques des sous-classes sont utilisés rarement.
J'ai utilisé la première approche. Sous extrêmes charges, la table "quelque chose" devient un goulot d'étranglement.
J'ai pris l'approche d'avoir des modèles DDL pour mes différents objets avec les spécialisations d'attribut étant ajoutée à la fin de la définition de la table.
Au niveau de DB si je devais vraiment représenter mes différentes classes comme un dossier "quelque chose", je mets une vue sur eux
SELECT "Something" fields FROM object1
UNION ALL
SELECT "Something" fields FROM object2
UNION ALL
SELECT "Something" fields FROM object3
Le défi est de savoir comment vous affectez une clé primaire sans heurts que vous avez trois objets indépendants. Généralement, les gens utilisent toutefois un UUID/GUID dans mon cas, la clé était un entier 64 bits généré dans une application basée sur une heure et une machine afin d'éviter les affrontements.
Si vous prenez cette approche, vous évitez le problème de l'objet "quelque chose" provoquant le verrouillage/blocage.
Si vous souhaitez modifier l'objet "quelque chose", cela peut être gênant maintenant, vous avez trois objets indépendants, qui nécessiteront tout ce qui nécessitera que leur structure soit modifiée.
Donc de résumer. L'option que l'on fonctionnera bien dans la plupart des cas dans la plupart des cas sous une charge sérieusement intense, vous pouvez observer le blocage de verrouillage qui nécessite la fractionnement de la conception.