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:
- Maintenir la troisième forme normale
- Maintenir l'intégrité référentielle
- Maintenez la contrainte que chaque compte appartient à une société ou à une personne physique.
- Préserver la capacité de récupérer des données simplement et directement
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 du customer_type
moment où vous joignez le 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 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'sOwnerTypeID
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.
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
.