INTRODUCTION ET INFORMATIONS PERTINENTES:
L'exemple suivant illustre le problème auquel je suis confronté:
L'animal a une race, qui peut être un chat ou un chien . Le chat peut être siamois ou persan . Le chien peut être un berger allemand ou un retriver du Labrador .
L'animal est une entité forte, tandis que sa race est un attribut qui peut avoir l'une des deux valeurs proposées (chat ou chien). Ces deux valeurs sont complexes (j'ai ajouté ici uniquement le type de chien / chat pour illustrer le problème, mais il peut également y avoir le nom du chat / chien et un tas d'autres choses).
PROBLÈME:
Je ne sais pas comment créer des tables relationnelles pour cet exemple.
MES EFFORTS POUR RÉSOUDRE LE PROBLÈME:
J'ai essayé de dessiner un diagramme ER, en utilisant la notation de Chen, qui représente le problème mais étant un débutant, je ne sais pas si je l'ai bien fait. Voici ce que j'ai:
Je m'excuse si j'ai dessiné quelque chose de mal, veuillez me corriger si c'est le cas. Je ne souhaite pas simplement obtenir une "solution gratuite" mais aussi apprendre à gérer ce problème afin de pouvoir le résoudre moi-même à l'avenir.
La seule chose qui me vient à l'esprit est de créer deux tables séparées, une pour les chats et une pour les chiens. De plus, l' attribut race dans la table Animal ne stockerait que la valeur cat ou dog . Quelque chose comme ça:
Animal< # Animal_ID, race, other attributes >
Cat < # Cat_ID, $ Animal_ID, breed >
Dog < # Dog_ID, $ Animal_ID, breed >
J'ai vraiment un mauvais pressentiment sur ma solution et je crains qu'elle ne soit mauvaise, d'où la question ci-dessous.
DES QUESTIONS:
- Comment puis-je transformer mon exemple en diagramme ER?
- Comment transformer ce diagramme ER en tables relationnelles?
Si des informations supplémentaires sont nécessaires, laissez un commentaire et je mettrai à jour mon message dès que possible. N'hésitez pas à ajouter des balises appropriées car je suis assez nouveau ici.
Je vous remercie.
la source
Réponses:
La structure appropriée pour ce scénario est un modèle de sous-classe / héritage, et est presque identique au concept que j'ai proposé dans cette réponse: Liste de valeur ordonnée hétérogène .
Le modèle proposé dans cette question est en fait assez proche en ce que l'
Animal
entité contient le type (ierace
) et les propriétés qui sont communes à tous les types. Cependant, deux modifications mineures sont nécessaires:Supprimez les champs Cat_ID et Dog_ID de leurs entités respectives:
Le concept clé ici est que tout est un
Animal
peu importe,race
:Cat
,Dog
,Elephant
et ainsi de suite. Étant donné que le point de départ, tout particulièrementrace
deAnimal
ne pas vraiment besoin d' un identifiant distinct depuis:Animal_ID
est uniqueCat
,Dog
et toutes autresrace
entités ajoutées à l'avenir ne représentent pas, en elles-mêmes, un élément particulierAnimal
; ils ont de sens que lorsqu'il est utilisé en combinaison avec les informations contenues dans l'entité mère,Animal
.Par conséquent, la
Animal_ID
propriété dans leCat
,Dog
, etc entités est à la fois le PK et le dos FK à l'Animal
entité.Différencier les types de
breed
:Le fait que deux propriétés partagent le même nom ne signifie pas nécessairement que ces propriétés sont identiques, même si le nom étant le même implique une telle relation. Dans ce cas, ce que vous avez vraiment est réellement
CatBreed
et enDogBreed
tant que "types" séparésNotes initiales
VARCHAR
mais si vous avez besoin de stocker quoi que ce soit en dehors de l'ensemble ASCII standard, vous devriez vraiment l'utiliserNVARCHAR
.Race
,CatBreed
etDogBreed
) sont pas auto-incrémentée (c. -à- IDENTITÉ en termes de T-SQL) , car ils sont des constantes d'application (ils font partie de l'application) qui sont des valeurs de recherche statiques dans la et sont représentés sous forme deenum
s en C # (ou dans d'autres langages). Si des valeurs sont ajoutées, elles sont ajoutées dans des situations contrôlées. Je réserve l'utilisation de champs d'incrémentation automatique pour les données utilisateur qui arrivent via l'application."Race" comme "Race" - Approche spécifique
Ce premier ensemble de tables sont les tables de recherche / types:
Cette deuxième inscription est la principale entité «animale»:
Cette troisième série de tableaux sont les entités sous-classe complémentaires qui complètent la définition de chacun
Race
deAnimal
:Le modèle utilisant un
breed
type partagé est affiché après la section "Notes supplémentaires".Notes complémentaires
breed
semble être un foyer de confusion. Il a été suggéré par jcolebrand (dans un commentaire sur la question) quibreed
est une propriété partagée entre les différentsrace
s, et les deux autres réponses l'ont intégré comme tel dans leurs modèles. Il s'agit toutefois d'une erreur, car les valeurs debreed
ne sont pas partagées entre les différentes valeurs derace
. Oui, je suis conscient que les deux autres modèles proposés tentent de résoudre ce problème en faisantrace
un parent debreed
. Bien que cela résout techniquement le problème des relations, cela n'aide pas à résoudre la question globale de la modélisation de ce qu'il faut faire des propriétés non communes, ni comment gérer unrace
qui n'en a pasbreed
. Mais, dans le cas où une telle propriété était garantie d'exister dans tous lesAnimal
s, je vais également inclure une option pour cela (ci-dessous).Animal
), ourace
s soient stockées dans l'Animal
entité, ce qui est une façon très plate (et presque non relationnelle) de représenter ces données. Oui, les gens le font tout le temps, mais cela signifie avoir de nombreux champs NULL par ligne pour les propriétés qui ne sont pas destinées à ce particulierrace
ET savoir quels champs par ligne sont associés au particulierrace
de cet enregistrement.race
deAnimal
dans le futur qui n'a pasbreed
de propriété. Et même si TOUSAnimal
ont unbreed
, cela ne changerait pas la structure en raison de ce qui a été noté précédemmentbreed
: celabreed
dépend durace
(c'est-breed
à- dire pourCat
n'est pas la même chose quebreed
pourDog
).La «race» comme approche de propriété commune / partagée
Notez s'il vous plaît:
Le SQL ci-dessous peut être exécuté dans la même base de données que le modèle présenté ci-dessus:
Race
tableau est le mêmeBreed
table est neuveAnimal
tableaux sont accompagnés d'un2
Breed
propriété désormais commune, il ne semble pas juste de ne pas l'avoirRace
noté dans l'entité principale / parent (même si elle est techniquement correcte sur le plan relationnel). Ainsi, les deuxRaceID
etBreedID
sont représentés dansAnimal2
. Afin d'éviter une incompatibilité entre leRaceID
noté dansAnimal2
et unBreedID
pour un autreRaceID
, j'ai ajouté un FK sur les deuxRaceID, BreedID
qui fait référence à une CONTRAINTE UNIQUE de ces champs dans laBreed
table. Je méprise généralement le fait de pointer un FK vers une CONTRAINTE UNIQUE, mais voici l'une des rares raisons valables de le faire. UNE CONTRAINTE UNIQUE est logiquement une «Clé alternative», ce qui la rend valable pour cette utilisation. Veuillez également noter que laBreed
table a toujours un PK justeBreedID
.BreedID
répéter le même sur différentes valeurs deRaceID
.BreedID
, il devrait donc être possible de référencer une valeur spécifique deBreed
sans avoir laRaceID
disponibilité.Breed
(et c'est pourquoi je préfère les tableauxRace
spécifiquesBreed
).Breed
ont les mêmes propriétés. Il n'y a pas de moyen facile dans ce modèle d'avoir des propriétés disparates entre lesDog
"races" et lesElephant
"races". Cependant, il existe toujours un moyen de le faire, ce qui est noté dans la section "Final Edit".Breed
course sur plusieurs courses. Je ne sais pas si c'est souhaitable de le faire (ou peut-être pas dans le concept d'animaux mais peut-être dans d'autres situations qui utiliseraient ce type de modèle), mais ce n'est pas possible ici.Édition finale (j'espère ;-)
Breed
, il est possible d'employer le même concept de sous-classe / héritage mais avecBreed
comme entité principale. Dans cette configuration, leBreed
tableau aurait les propriétés communes à tous les types deBreed
(tout comme leAnimal
tableau) etRaceID
représenterait le type deBreed
(comme il le fait dans leAnimal
tableau). Ensuite , vous avez des tables sous - classe tels queBreedCat
,BreedDog
et ainsi de suite. Pour les petits projets, cela pourrait être considéré comme une «ingénierie excessive», mais il est mentionné comme une option pour les situations qui en bénéficieraient.Pour les deux approches, il est parfois utile de créer des vues sous forme de raccourcis vers les entités complètes. Par exemple, considérez:
CreatedDate
champ serait ajouté à laAnimal
table. Ce champ n'est nécessaire dans aucune des tables de sous-classe (par exempleAnimalCat
) car les lignes insérées pour les deux tables doivent être effectuées en même temps dans une transaction.LastModifiedDate
champ serait ajouté à laAnimal
table et à toutes les tables de sous-classe. Ce champ n'est mis à jour que si cette table particulière est mise à jour: si une mise à jour se produit dansAnimalCat
mais pas dansAnimal
pour un particulierAnimalID
, alors seul leLastModifiedDate
champ dansAnimalCat
sera défini.la source
D
, donc je voulais appliquer la méthode de votre réponse. Deux entités ont un attribut communE
qui n'est pas présent dans la troisième entité. Dois-je ignorer ce fait et appliquer une solution standard, ou existe-t-il un moyen d'optimiser davantage ma conception?Tout d'abord, vous réussissez bien à faire la distinction entre la modélisation ER et la modélisation relationnelle. Beaucoup de débutants ne le font pas.
Voici quelques mots à la mode que vous pouvez utiliser pour rechercher des articles utiles sur le Web.
Votre cas est un cas classique de classe / sous-classe ou, si vous le souhaitez, de type / sous-type.
L'expression utilisée dans la modélisation ER est "généralisation / spécialisation". Et de nombreux articles le montrent sous quelque chose appelé modélisation EER (Enhanced Entity-Relationship). Ce n'était pas dans la présentation originale de Peter Chen de la modélisation ER. Il a été ajouté plus tard. Pour un assez bon résumé de gen / spec au format pdf, cliquez ici
Ensuite, lors de la conversion d'un cas de classe / sous-classe en modélisation relationnelle, vous concevez des tables. Il existe plusieurs approches. Les deux principales approches sont appelées héritage de table unique et héritage de table de classe. Chacun a ses avantages et ses inconvénients. La meilleure présentation de ces deux designs vient de Martin Fowler. Vous pouvez voir son plan ici et ici .
Le gros avantage de l'héritage d'une table unique est la simplicité. Tout est stocké dans une seule table. Le gros inconvénient est beaucoup de NULLS. Cela peut gaspiller de l'espace et du temps et entraîner une logique confuse.
L'héritage de table de classe nécessite des jointures, mais elles sont simples et rapides. Surtout si vous utilisez une technique appelée clé primaire partagée, dans laquelle le PK dans les tables de sous-classe est une copie du PK dans la table de superclasse. Vous pouvez créer des vues pour chaque sous-classe qui joignent des données de super-classe à des données de sous-classe.
Enfin, il y a une balise dans cette zone qui recueille des questions comme la vôtre ensemble.
Le voici: sous - types
la source
Je vois sur la conception possible
Table
Race
Table
Breed
Table
Animal
Ces PK ci-dessus seraient une colonne à incrémentation automatique. Les autres colonnes du
Animal
tableau peuvent être nommées en conséquence.la source
Votre méthode actuelle n'est pas mauvaise. Cependant, si vous allez ajouter plus de races plus tard (oiseau, poisson, etc.), la création d'une table distincte pour chacune pourrait être fastidieuse. Je recommanderais quelque chose comme ceci:
À ma connaissance, une race ne devrait avoir qu'une seule race. Donc, si vous stockez la race dans la table des animaux, vous pourrez déterminer la race en vous joignant à la table des races. De toute évidence, ajoutez tout autre attribut (nom, description, etc.) aux tables de race et de race si nécessaire.
la source