Je dois modéliser une situation où j'ai une table Chequing_Account (qui contient le budget, le numéro iban et d'autres détails du compte) qui doit être liée à deux tables Person et Corporation différentes qui peuvent toutes deux avoir 0, 1 ou plusieurs comptes de chèques.
En d'autres termes, j'ai deux relations 1 à plusieurs avec le même compte de chèques de table
Je voudrais entendre des solutions à ce problème qui respectent les exigences de normalisation. La plupart des solutions que j'ai entendues sont:
1) trouver une entité commune à laquelle appartiennent à la fois la personne et la société et créer une table de liens entre celle-ci et la table Chequing_Account, ce n'est pas possible dans mon cas et même si c'était le cas, je veux résoudre le problème général et non cette instance spécifique.
2) Créez deux tables de liens PersonToChequingAccount et CorporationToChequingAccount qui relient les deux entités aux comptes de chèques. Cependant, je ne veux pas que deux personnes aient le même compte de chèques, et je ne veux pas qu'une personne physique et une société partagent un compte de chèques! voir cette image
3) Créez deux clés étrangères dans le compte de chèques qui pointent vers la société et la personne physique, mais j'imposerais donc qu'une personne et une société peuvent avoir de nombreux comptes de chèques, mais je devrais m'assurer manuellement que pour chaque ligne de compte de chèques, les deux relations ne pointent pas vers Société et personne physique, car un compte de chèques appartient soit à une société, soit à une personne physique. voir cette image
Existe-t-il une autre solution plus propre à ce problème?
la source
OwnerTypeID
dans leChecquingAccount
tableau, avec1=Corporation
et2=NaturalPerson
? De cette façon, vous n'en avez besoin que d'unOwnerID
dans leChecquingAccount
tableau, que vous pouvez indexer avec leOwnerTypeID
.CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)
je préfère de loin la solution 1 (mais c'est juste moi). C'est beaucoup plus "propre".ChecquingAccount
tableau un enregistrement deOwnerTypeID=1
etOwnerID=123
, indiquant qu'il s'agit d'un typeCorporation
, donc un ID123
dans leCorporation
tableau. Le OwnerTypeID vous indique quelle table, et le OwnerID vous indique l'ID dans cette table.Customers
table.Réponses:
Les bases de données relationnelles ne sont pas conçues pour gérer parfaitement cette situation. Vous devez décider de ce qui est le plus important pour vous et ensuite faire vos compromis. Vous avez plusieurs objectifs:
Le problème est que certains de ces objectifs se font concurrence.
Solution de sous-typage
Vous pouvez choisir une solution de sous-typage dans laquelle vous créez un super-type qui intègre à la fois des sociétés et des personnes. Ce super-type aurait probablement une clé composée de la clé naturelle du sous-type plus un attribut de partitionnement (par exemple
customer_type
). C'est très bien en ce qui concerne la normalisation et cela vous permet d'appliquer l'intégrité référentielle ainsi que la contrainte que les sociétés et les personnes s'excluent mutuellement. Le problème est que cela rend la récupération des données plus difficile, car vous devez toujours créer une branche en fonction ducustomer_type
moment où vous joignez le compte au titulaire du compte. Cela signifie probablement utiliserUNION
et avoir beaucoup de SQL répétitif dans votre requête.Solution à deux clés étrangères
Vous pouvez choisir une solution dans laquelle vous conservez deux clés étrangères dans votre table de compte, une pour la société et une pour la personne. Cette solution vous permet également de maintenir l'intégrité référentielle, la normalisation et l'exclusivité mutuelle. Il présente également le même inconvénient de récupération de données que la solution de sous-typage. En fait, cette solution est semblable à la solution de sous-typage, sauf que vous arrivez au problème de branchement de votre logique de jonction "plus tôt".
Néanmoins, de nombreux modélisateurs de données considéreraient cette solution inférieure à la solution de sous-typage en raison de la manière dont la contrainte d'exclusivité mutuelle est appliquée. Dans la solution de sous-typage, vous utilisez des clés pour appliquer l'exclusivité mutuelle. Dans la solution à deux clés étrangères, vous utilisez une
CHECK
contrainte. Je connais des gens qui ont un parti pris injustifié contre les contraintes de contrôle. Ces personnes préféreraient la solution qui garde les contraintes dans les clés.Solution d'attribut de partitionnement "dénormalisé"
Il existe une autre option où vous conservez une seule colonne de clé étrangère dans la table de compte de chèques et utilisez une autre colonne pour vous dire comment interpréter la colonne de clé étrangère (RoKa's
OwnerTypeID
colonne). Cela élimine essentiellement la table de super-type dans la solution de sous-typage en dénormalisant l'attribut de partitionnement de la table enfant. (Notez qu'il ne s'agit pas strictement de «dénormalisation» selon la définition formelle, car l'attribut de partitionnement fait partie d'une clé primaire.) Cette solution semble assez simple car elle évite d'avoir une table supplémentaire pour faire plus ou moins la même chose et cela réduit le nombre de colonnes de clé étrangère à un. Le problème avec cette solution est qu'elle n'évite pas le branchement de la logique de récupération et de plus, elle ne vous permet pas de maintenir l' intégrité référentielle déclarative . Les bases de données SQL n'ont pas la capacité de gérer une seule colonne de clé étrangère pour l'une des tables parent multiples.Solution de domaine de clé primaire partagée
Une façon dont les gens traitent parfois ce problème est d'utiliser un seul pool d'ID afin qu'il n'y ait aucune confusion pour un ID donné, qu'il appartienne à un sous-type ou à un autre. Cela fonctionnerait probablement assez naturellement dans un scénario bancaire, car vous n'allez pas émettre le même numéro de compte bancaire à la fois à une société et à une personne physique. Cela a l'avantage d'éviter la nécessité d'un attribut de partitionnement. Vous pouvez le faire avec ou sans table de super-type. L'utilisation d'une table de super-type vous permet d'utiliser des contraintes déclaratives pour appliquer l'unicité. Sinon, cela devrait être appliqué de manière procédurale. Cette solution est normalisée mais elle ne vous permettra pas de maintenir l'intégrité référentielle déclarative à moins de conserver la table de super-type. Il ne fait toujours rien pour éviter une logique de récupération complexe.
Vous pouvez donc voir qu'il n'est pas vraiment possible d'avoir une conception propre qui respecte toutes les règles, tout en gardant la récupération de vos données simple. Vous devez décider où seront vos compromis.
la source
corporation_id
et queperson_id
vous auriez essentiellement la solution de sous-typage, sauf que la table de super-type aurait été divisée en deux et que la clé étrangère aurait été inversée, de sorte que les gens ne pourraient pas détenir plusieurs comptes. Ce genre de défait le but.RefID
etRefTable
oùRefTable
est un identifiant fixe qui identifie la table cible. Il existe de nombreux cas d'utilisation pour ce type de clé et son trop pour maintenir 10 ou plusieurs tables d'association / sous-type pour appliquer l'intégrité. Pour ces cas, je l'ai créékey
moi - même.