Je rencontre une situation dans la base de données assez fréquemment où une table donnée peut FK vers l'une des nombreuses tables parentales différentes. J'ai vu deux solutions au problème, mais aucune n'est personnellement satisfaisante. Je suis curieux de savoir quels autres modèles vous avez vus là-bas? Y a-t-il une meilleure façon de le faire?
Un exemple artificiel
Supposons que mon système le soit Alerts
. Des alertes peuvent être reçues pour une variété d'objets - Clients, Actualités et Produits. Une alerte donnée peut concerner un et un seul élément. Pour une raison quelconque, les clients, les articles et les produits évoluent rapidement (ou sont localisés), de sorte que le texte / les données nécessaires ne peuvent pas être extraits dans les alertes lors de la création d'une alerte. Compte tenu de cette configuration, j'ai vu deux solutions.
Remarque: ci - dessous DDL est pour SQL Server mais ma question devrait être applicable à n'importe quel SGBD.
Solution 1 - FKeys Nullable multiples
Dans cette solution, la table qui établit un lien vers l'une des nombreuses tables a plusieurs colonnes FK (par souci de concision, le DDL ci-dessous n'affiche pas la création FK). LE BON - Dans cette solution, c'est bien d'avoir des clés étrangères. L'optinalité nulle des FK rend cela pratique et relativement facile pour ajouter des données précises. THE BAD Querying n'est pas génial car il nécessite des instructions N LEFT JOINS ou N UNION pour obtenir les données associées. Dans SQL Server, en particulier les LEFT JOINS empêchent la création d'une vue indexée.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
ProductID int null,
NewsID int null,
CustomerID int null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
ALTER TABLE Alert WITH CHECK ADD CONSTRAINT CK_OnlyOneFKAllowed
CHECK (
(ProductID is not null AND NewsID is null and CustomerID is null) OR
(ProductID is null AND NewsID is not null and CustomerID is null) OR
(ProductID is null AND NewsID is null and CustomerID is not null)
)
Solution 2 - Un FK dans chaque table parent
Dans cette solution, chaque table «parent» a un FK dans la table Alert. Il facilite la récupération des alertes associées à un parent. En revanche, il n'y a pas de véritable chaîne de l'alerte à qui fait référence. En outre, le modèle de données autorise les alertes orphelines - lorsqu'une alerte n'est pas associée à un produit, une actualité ou un client. Encore une fois, plusieurs LEFT JOINs pour comprendre l'association.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
Est-ce juste la vie dans une base de données de relations? Y a-t-il d'autres solutions que vous avez trouvées plus satisfaisantes?
la source
Alertable
. Ça a du sens?Réponses:
Je comprends que la deuxième solution n'est pas applicable car elle n'offre pas de relation un (objet) à plusieurs (alerte).
Vous êtes coincé à seulement deux solutions en raison de la stricte conformité 3NF.
Je voudrais concevoir un schéma de couplage moindre:
Ou, si la relation d'intégrité est obligatoire, je pourrais concevoir:
En tous cas...
Trois solutions valides et une autre à considérer pour de nombreuses relations (objets) à un (alerte) ...
Ceux-ci présentés, quelle est la morale?
Ils diffèrent subtilement et pèsent de la même manière sur les critères:
Alors, choisissez ce confort pour vous.
la source
J'ai utilisé des tables de jointure gérées par déclencheur. la solution fonctionne plutôt bien en dernier recours si la refactorisation de la base de données n'est pas possible ou souhaitable. L'idée est que vous avez une table qui est là juste pour gérer les problèmes de RI, et tous les DRI vont à l'encontre.
la source