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
J'aimerais 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 entreprise peuvent avoir plusieurs 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?
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, puis faire des 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 où vous créez un super-type qui intègre à la fois les sociétés et les 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 basée sur customer_type
lorsque vous joignez un compte au titulaire du compte. Cela signifie probablement utiliser UNION
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 similaire à la solution de sous-typage, sauf que vous arrivez plus tôt au problème de branchement de votre logique de jonction.
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 contrainte CHECK
. 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 dans laquelle vous conservez une seule colonne de clé étrangère dans la table du compte de chèques et utilisez une autre colonne pour vous indiquer comment interpréter la colonne de clé étrangère (colonne OwnerTypeID
de RoKa). 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 la ramification 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 possibilité 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.