我应该添加传递外键吗?

vek*_*tor 13 foreign-key database-design

简单的例子:有一张客户表。

create table Customers (
  id integer,
  constraint CustomersPK primary key (id)
)
Run Code Online (Sandbox Code Playgroud)

数据库中的所有其他数据都应该链接到 a Customer,例如Orders看起来像这样:

create table Orders (
  id integer,
  customer integer,
  constraint OrdersPK primary key (customer, id),
  constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Run Code Online (Sandbox Code Playgroud)

假设现在有一个表链接到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)
)
Run Code Online (Sandbox Code Playgroud)

我应该从Itemsto添加一个单独的外键Customers吗?

...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Run Code Online (Sandbox Code Playgroud)

取而代之的是一张图片:我应该添加虚线/FK吗?

简单示例架构


编辑:我已向表中添加了主键定义。我想重申我上面提出的观点:数据库基本上是由客户孤立的,作为一种正确性/安全措施。因此,所有主键都包含customerID。

Dam*_*vic 6

我认为这是最初的想法。

在此处输入图片说明

首先要注意的是 LineItem 表上的 PK 具有三个属性{CustomerID, CustomerOrderNo, OdrerItemNo},而您的示例中只有两个属性。

要注意的第二件事是对id属性使用通用名称所导致的混淆。

CustomerOrderNo理想情况下应(1,2,3 ......)为每一个客户和OrderItemNo(1,2,3 ......)每个订单。

好吧,如果可能的话,这很好,但需要查询查找先前的最大值,例如

select max(CustomerOrderNo)
from Order 
where CustomerID = specific_customer ; 
Run Code Online (Sandbox Code Playgroud)

这在高交易量环境中通常不是首选,因此通常会看到它们被自动增量替换,基本上用于相同的目的。确实,这个自动增量现在是独一无二的,因此它可以用作密钥——但您可以选择将其视为OrderItemNo.

因此,通过一些重命名CustomerOrderNo -> OrderNoOrderItemNo->ItemNo您可能会到达此模型

在此处输入图片说明

所以现在如果你看看Order以下是独一无二的

{OrderNo}             -- PK
{CustomerID, OrderNo} -- superkey,  AK on the diagram.
Run Code Online (Sandbox Code Playgroud)

请注意,{CustomerID, OrderNo}它传播到LineItem用作 FK。

如果你眯着眼睛,这与你的例子很接近,但PKs {ItemNo} and {OrderNo}只有 -- 而不是你的例子中的两列 PK。

现在的问题是,为什么不简化成这样呢?

在此处输入图片说明

这很好,但是引入了PATH DEPENDENCE——不能直接join LineItemwith Customer,必须Order在join中使用。


如果可能,我更喜欢第一种情况——你选择你最喜欢的。显然,在这三种情况下,不需要直接 FK from LineItemto Customer