Exemple simple: il y a une table des clients.
create table Customers (
id integer,
constraint CustomersPK primary key (id)
)
Toutes les autres données de la base de données doivent être liées à un Customer
, par exemple, cela Orders
ressemble à ceci:
create table Orders (
id integer,
customer integer,
constraint OrdersPK primary key (customer, id),
constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Supposons maintenant qu'il existe une table reliant Orders
:
create table Items (
id integer,
customer integer,
order integer,
constraint ItemsPK primary key (customer, id),
constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)
Dois-je ajouter une clé étrangère distincte de Items
à Customers
?
...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Une image à la place: dois-je ajouter la ligne pointillée / FK?
Modifier: j'ai ajouté des définitions de clé primaire aux tables. Je voudrais réitérer sur le point que j'ai soulevé ci-dessus: la base de données est essentiellement cloisonnée par les clients, en tant que mesure d'exactitude / sécurité. Par conséquent, toutes les clés primaires contiennent l' customer
ID.
database-design
foreign-key
vektor
la source
la source
Réponses:
Je pense que c'est l'idée originale.
La première chose à noter est que le PK sur la table LineItem a trois attributs
{CustomerID, CustomerOrderNo, OdrerItemNo}
, contre seulement deux dans votre exemple.La deuxième chose à noter est la confusion résultant de l'utilisation du
id
nom générique pour un attribut.L'
CustomerOrderNo
idéal devrait être (1,2,3 ..) pour chaque client etOrderItemNo
(1,2,3 ...) pour chaque commande.Eh bien, c'est bien si possible, mais nécessite une requête recherchant la valeur maximale précédente, comme
ce qui n'est souvent pas préféré dans les environnements à volume de transaction élevé, il est donc courant de les voir remplacés par une incrémentation automatique, servant essentiellement le même objectif. Il est vrai que cet auto-incrément est désormais unique, il peut donc être utilisé comme une clé - mais vous pouvez choisir de le considérer comme un compromis nécessaire pour le
OrderItemNo
.Donc, avec quelques renommage
CustomerOrderNo -> OrderNo
etOrderItemNo
->ItemNo
vous pouvez arriver à ce modèleAlors maintenant, si vous regardez
Order
ce qui suit est uniqueNotez que
{CustomerID, OrderNo}
se propage vers leLineItem
pour servir de FK.Si vous
PKs {ItemNo} and {OrderNo}
plissez les yeux , cela est proche de votre exemple, mais avec seulement - par opposition aux PK à deux colonnes de votre exemple.Maintenant, la question est, pourquoi ne pas simplifier à quelque chose comme ça?
Ce qui est bien, mais introduit PATH DEPENDANCE - vous ne pouvez pas joindre
LineItem
avecCustomer
directement, devez utiliserOrder
dans la jointure.Je préfère le premier cas lorsque cela est possible - vous choisissez votre préféré. Et évidemment, il n'y a pas besoin de FK direct de
LineItem
àCustomer
dans ces trois cas.la source
L '"article" ne doit pas référencer directement le "client", car cela est impliqué par la "commande" de l'article. Ainsi, vous n'aurez pas du tout besoin des colonnes "client" de la table "articles".
La relation de l'article avec le client est assurée avec la clé étrangère existante.
Si orders.id est une colonne d'identité, envisagez de supprimer ensemble items.customer.
la source
customer
dans toutes les tables (et donc de cloisonner la DB) est une approche inhabituelle. Je dois avouer que c'est juste quelque chose que j'ai vu dans mon travail précédent. Cela a-t-il un sens pour vous? Avez-vous déjà vu un tel design auparavant?