Réponses à vos questions individuelles
Si je veux ajouter une colonne Club
décrivant le propriétaire, qui sera également membre, quelle est la meilleure approche sans avoir le même membre répertorié deux fois?
Si, comme indiqué dans vos spécifications a Person can be a Member of only one Club
, et que vous souhaitez stocker cette donnée simplement comme vraie ou fausse , une option consiste à ajouter une BIT(1)
ou une colonne BOOLEAN
( TINYINT
) au Person
tableau, et vous souhaiterez peut-être appeler cette colonne IsClubOwner
. De cette façon, vous pouvez enregistrer le fait qu'une personne déterminée est propriétaire d' un club exclusivement une fois. En dehors de cela, cette méthode permet également de conserver plusieurs personnes en tant que propriétaires de la même occurrence de club . Vous pouvez voir une représentation au niveau logique de cette approche dans la figure 1 .
Cependant, vous recherchez la meilleure approche et, selon mon expérience, une telle approche implique le développement d'une structure beaucoup plus extensible et polyvalente. À cet égard, suivez la progression d'un exercice de modélisation pour ces points et d'autres ci-dessous, dans les sections intitulées «Couvrir vos spécifications restantes», «Personne en tant que membre de plusieurs clubs» et «Membre et propriétaire en tant que types d'entités distinctes».
Dois-je mettre toutes mes tables sur l'incrémentation automatique d'un id
ou ce serait une mauvaise idée? (avantages / inconvénients?)
Si vous êtes confronté à une exigence explicite qui indique la définition d'une table avec une colonne de ces caractéristiques, et que cette colonne a une signification contextuelle valide ou sert un objectif particulier comme être un substitut pour une large clé naturelle (PK), alors oui, vous devez procéder de cette façon.
Sinon, si vous n'avez pas dit cette exigence, je considère que ce ne serait pas nécessaire car vous devez stocker et gérer une colonne supplémentaire vide de sens et (peut-être?) Également un INDEX supplémentaire dans votre base de données.
Comme d'habitude, vous devez analyser chaque cas ainsi que ses répercussions globales afin de décider comment continuer.
Si j'ajoute des clés étrangères dans l'onglet des clés étrangères, celles-ci correspondront-elles automatiquement à la bonne table ou dois-je également les ajouter aux colonnes?
À cet égard, mon conseil pour vous est de créer votre structure de base de données manuellement, de coder vos propres DDL
déclarations jusqu'à ce que vous compreniez bien le sujet. Si vous le faites, il vous sera plus facile de comprendre les processus que les outils graphiques exécutent «sous le capot».
Pour moi, par exemple, créer une déclaration comme celle-ci:
CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)
Est beaucoup plus instructif que d'utiliser des outils GUI pour exécuter ce type de tâches, surtout maintenant que vous construisez vos premières conceptions.
Et ma question probablement la plus noble de toutes ... Est-ce que je mets les clés étrangères de phone_number
et email
dans leur table respective en les reliant à person_id
ou devrais-je mettre phone_number
et email
ids
dans la table person?
Personnellement, je pense que cette question et toutes vos autres questions sont parfaitement valables et bien contextualisées .
Revenant aux aspects techniques qui nous concernent, cette enquête précise offre une bonne occasion de revoir les deux affirmations suivantes:
A Person can be reached through zero-one-or-many PhoneNumbers
A PhoneNumber can be used to reach one-to-many People
Ainsi, on peut conclure qu'il existe une relation plusieurs-à-plusieurs entre Person
et PhoneNumber
, par conséquent, je suggère la création d'une table associative nommée PersonPhoneNumber
pour représenter ladite relation dans votre base de données. Le PK de ce tableau doit être composé de deux colonnes différentes: PersonId
(une clé étrangère [FK] pointant vers Person.PersonId
) et PhoneNumber
(un FK qui fait référence à PhoneNumber.Number
). Pour une description logique de tout ce qui précède, voir la figure 1 .
En revanche, examinons les deux propositions qui suivent:
A Person can be contacted via zero-one-or-many EmailAddresses
An EmailAddress can be used to contact exactly one Person
Ensuite, oui, vous devez définir un référentiel FK à Person
partir du EmailAddress
tableau, et ce tableau doit également avoir un PK composite, qui serait composé des colonnes PersonId
et Address
. De cette manière, vous pouvez vous assurer que la même combinaison de EmailAddress.PersonId
et EmailAddress.Address
ne peut être insérée qu'une seule fois.
Si vous souhaitez également vous assurer qu'un élément donné EmailAddres.Address
peut être stocké dans une seule ligne, il vous suffit d'établir une CONTRAINTE UNIQUE pour cette colonne.
Modèles de données logiques proposés
Afin d'exposer mes suggestions plus clairement, j'ai inclus quatre modèles logiques IDEF1X [1] distincts qui sont illustrés dans les figures 1 , 2 , 3 et 4 . Je vais fournir une explication des fonctionnalités les plus pertinentes affichées dans chacun d'eux dans les sections correspondantes. Vous pouvez également télécharger depuis Dropbox un PDF qui intègre dans un même modèle la majorité des éléments en discussion.
Couvrant vos spécifications restantes
Relier les personnes et les adresses
Inspectons les deux assertions suivantes (légèrement reformulées) qui sont pertinentes pour les personnes et les adresses :
A Person can only have one Address
An Address can belong to different People (couples or siblings)
Ainsi, pour faire face à ces restrictions, vous pouvez choisir d'implémenter un modèle de données similaire à celui que vous pouvez voir dans la figure 1 .
En tenant compte du modèle référencé, vous devez suivre les étapes suivantes:
Créez une table appelée PersonAddress
correction d'une relation entre Person
et Address
. Définissez les colonnes PersonId
et AddressId
le PK composé de ce tableau.
Configurez une CONTRAINTE UNIQUE pour la PersonAddress.PersonId
colonne pour vous assurer qu'une valeur spécifique peut être insérée dans au plus une ligne de ladite table. Au niveau logique, cette circonstance implique qu'elle PersonAddress.PersonId
est devenue une CLÉ ALTERNATIVE [2] .
Si la valeur de AddressId
dans une PersonAddress
tentative d'insertion déterminée n'a pas déjà été stockée, laissez l'insertion continuer, sinon, lorsqu'une telle valeur existe déjà dans une ligne, vous devez vérifier que (a) celui PersonId
qui s'est enregistré qui AddressId
est également enregistré en tant que Marriage.WifeId
si le PersonId
est un mâle (donnée dérivée via le Person.GenreCode
) ou (b) qui PersonId
est le Marriage.HusbandId
lorsque le PersonId
est une femelle (dérivé en vertu de Person.GenreCode
, également). Si l'une de ces conditions est remplie dans la situation appropriée, vous devez laisser l'insertion se poursuivre.
Si les conditions ci-dessus ne sont pas remplies, il y a encore une chance qu'une PersonAddress
tentative d'insertion réussisse. Vous devez vérifier que la PersonId
valeur impliquée dans ladite tentative d'insertion partage au moins une Progeny.ParentId
avec celle PersonId
qui a déjà enregistré le PersonAddress.AddressId
. Si cette condition est remplie, cela signifie qu'ils sont stockés comme Siblings
dans la base de données, donc cet INSERT doit réussir.
Comme dans toute implémentation de base de données relationnelle, vous devriez sérieusement envisager d'exécuter vos DML
opérations dans ACID Transactions afin de pouvoir protéger l' intégrité et la cohérence des données avec lesquelles vous travaillez.
Assister aux exigences que vous avez ajoutées dans les commentaires: adresses et numéros de téléphone desservant à la fois les clubs et les personnes
À condition que vous souhaitiez donner la possibilité aux adresses et aux numéros de téléphone de servir à la fois les personnes et les clubs , vous pouvez utiliser une relation supertype-sous-type . Voici une réponse dans laquelle je donne un traitement plus détaillé à ce type de structures, au cas où vous seriez intéressé.
Dans le scénario actuel, vous pourriez définir Person
et en Club
tant que sous-types d'une nouvelle entité nommée Party
, un terme couramment utilisé dans les cercles juridiques pour représenter (a) une personne ou (b) un groupe de personnes (comme indiqué dans le sens n ° 6 ). Avec cette méthode, les relations entre Addresses
(ou PhoneNumbers
) et People
et Clubs
seraient définies par Party
le biais du supertype. Voir la figure 2 pour une description de cette suggestion.
Fête et adresse
On peut donc lire dans ce nouveau modèle que:
A Party keeps zero-one-or-many Addresses
An Address is kept by one-to-many Parties
Ainsi, il existe une relation plusieurs-à-plusieurs impliquant Party
et Address
qui est exprimée par le biais de l' PartyAddress
entité.
Fête et numéro de téléphone
De plus, nous pouvons interpréter cela:
A Party is reached through zero-one-or-many PhoneNumbers
A PhoneNumber is used by one-to-many Parties
C'est pourquoi j'ai ajouté l' PartyPhoneNumber
entité qui décrit l'association plusieurs-à-plusieurs qui prend effet entre les types d'entité Party
et PhoneNumber
.
Fête et club ou personne
Ensuite, on peut également lire que:
A Party is either a Club or a Person
Par conséquent, Party
fournit une connexion de deux Clubs
ou People
de Addresses
(ou PhoneNumbers
).
Personne en tant que membre de plusieurs clubs
Comme @aldwinaldwin le mentionne dans sa réponse, si vous souhaitez fournir la fonctionnalité permettant à une personne d'être membre de plusieurs clubs , vous pouvez inclure une table appelée ClubMember
qui agirait comme une autre relation de plusieurs à plusieurs, cette fois, naturellement , interconnexion Person
et Club
.
Je vais ajouter à ce qui précède que ce tableau peut également être utile dans le but de stocker toute personne concrète en tant que propriétaire de plusieurs clubs , grâce à l'inclusion de la IsClubOwner
colonne booléenne déjà mentionnée . En fait, on peut dire que ce nouveau tableau est la représentation d'un type d'entité intégrale à part entière.
Comme le montre la figure 3 , un tel tableau nécessite un PK composite composé des colonnes ClubId
et MemberId
(un nom de rôle [3] donné à PersonId
), et ces colonnes doivent être définies également comme des FK pointant, de manière correspondante, vers Club
et Person
.
Une structure plus adaptable
En utilisant ce paramètre, vous pouvez également respecter la règle initiale qui le stipule a Person can be a member of only one Club
, mais il vous suffit d'ajouter une CONTRAINTE UNIQUE à la MemberId
colonne, de sorte qu'une certaine valeur puisse être entrée en une seule fois. Donc, comme vous pouvez le constater, cette structure est beaucoup plus adaptable que celle illustrée à la figure 1 , car en supprimant la CONTRAINTE UNIQUE (ou INDEX), vous ouvririez la fonctionnalité susmentionnée de permettre à une personne de devenir membre de différents clubs au en même temps.
Membre et propriétaire en tant que types d'entité distincts
Comme vous le savez, le stockage de plusieurs faits sur le rôle joué par une personne en tant que propriétaire d'un club - outre sa simple existence dans un attribut vrai ou faux - peut être très avantageux. Par exemple, vous pouvez garder la date où une certaine personne est devenu le propriétaire d'un club , vous pouvez donc gérer cette situation en introduisant un type d'entité distincte appelée ClubOwner
, tel que présenté dans la figure 4 .
Une fois que vous avez construit une table basée sur ce nouveau type d'entité, vous pouvez ajouter les colonnes d'ajustement qui représentent les caractéristiques qui entrent en jeu exclusivement lorsque a Person
est la Owner
de a Club
. Comme illustré, ce tableau contiendrait un PK composé des colonnes FK référençant Person.PersonId
et Club.ClubId
, de cette façon, n'importe quelle combinaison de ClubOwner.OwnerId
(ou ClubOwner.PersonId
, si vous préférez) et ClubOwner.ClubId
peut être inséré en une seule occasion.
Bien sûr, avec cette configuration, vous pouvez toujours dériver sous forme booléenne si a Person
est le Owner
d'un particulier Club
à l'aide d'une requête qui retourne une valeur scalaire qui peut être évaluée à vrai ou faux .
Remarques
1. La définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation de données hautement recommandable qui a été définie comme norme en décembre 1993 par le National Institute of Standards and Technology ( NIST ) des États-Unis . Il est solidement basé sur (a) certains des articles théoriques rédigés par l' auteur du modèle relationnel , c'est-à-dire le Dr EF Codd ; sur (b) la théorie Entité-Relation , développée par le Dr PP Chen ; et également sur (c) la technique de conception de bases de données logiques , créée par Robert G. Brown . Il convient de noter que IDEF1X étaitformalisé par une logique de premier ordre .
2. Une TOUCHE ALTERNATIVE est un attribut (ou une combinaison d'attributs) qui contient des valeurs qui identifient de manière unique une occurrence d'entité mais qui n'a pas été choisie comme PK du type d'entité pertinent; chaque type d'entité peut avoir zéro, une ou plusieurs CLÉS ALTERNATIVES. Dans un modèle IDEF1X, ils sont indiqués comme «AK» plus son numéro respectif, par exemple AK1, AK2, etc. Ils sont généralement implémentés dans une structure SQL DDL via une CONTRAINTE UNIQUE (ou un INDEX UNIQUE ).
3. Les noms de rôle sont des dénotations (ou alias) attribuées aux attributs FK afin d'exprimer la signification qu'ils détiennent dans le cadre de leur entité respective. Leur utilisation est recommandée depuis 1970 par le Dr Codd dans son article fondateur intitulé «Un modèle relationnel de données pour les grandes banques de données partagées» . Pour sa part, IDEF1X - maintenir la fidélité en ce qui concerne les pratiques relationnelles - préconise également le nommage des rôles.
clubId
saisir le numéro de téléphone et laisser le club ou la personne à zéro?