Should I add transitive foreign keys?
I think this is the original idea.
First thing to notice is that the PK on the LineItem table has three attributes {CustomerID, CustomerOrderNo, OdrerItemNo}
, as opposed to just two in your example.
Second thing to note is the confusion resulting from the use of the generic id
name for an attribute.
The CustomerOrderNo
should ideally be (1,2,3..) for each customer and OrderItemNo
(1,2,3 ...) for each order.
Well, this is nice if possible, but requires a query looking for the previous max value, like
select max(CustomerOrderNo)
from Order
where CustomerID = specific_customer ;
which is often not preferred in high-transaction-volume environments, so it is common to see these replaced by an auto-increment, essentially serving the same purpose. It is true that this auto-incremet is now unique, hence it can be used as a KEY -- but you may choose to look at it as a necessary compromise for the OrderItemNo
.
So, with some renaming CustomerOrderNo -> OrderNo
and OrderItemNo
-> ItemNo
you may arrive to this model
So now if you look at the Order
the following are unique
{OrderNo} -- PK
{CustomerID, OrderNo} -- superkey, AK on the diagram.
Note that {CustomerID, OrderNo}
is propagated to the LineItem
to serve as a FK.
If you squint a bit, this is close to your example, but with PKs {ItemNo} and {OrderNo}
only -- as opposed to two column PKs from your example.
Now the question is, why not simplify to something like this?
Which is fine, but introduces PATH DEPENDENCE -- you can not join LineItem
with Customer
directly, must use Order
in the join.
I prefer the first case when possible -- you choose your favourite. And obviously, there is no need for direct FK from LineItem
to Customer
in these three cases.
The "item" shouldn't reference the "customer" directly, because this is implied by the item's "order". So, you won't need the "customer" columns on the "items" table at all.
The item's relation to the customer is ensured with the existing foreign key.
If orders.id is an identity column, consider removing items.customer alltogether.