可空的外键可行吗?

时间:2019-03-25 22:16:54

标签: sql-server sql-server-2012

请考虑以下表格来创建简单的订单:

Customer(CustomerId, Name)
Order(OrderId, CustomerId)
OrderLine(OrderLineId, OrderId, CatalogItemId)

上面的表格是典型的。但是,以下内容并不常见,因为其中包含CustomerId:

CatalogItem(CatalogItemId, Description, CustomerId)

换句话说,每个目录项仅适用于一个客户。但是,实际需要的是将目录项分配给特定客户或任何客户。

建模的最佳方法是什么? (这可能很简单,只需将CustomerId设置为null,但我不确定,目前还不是这样。)

然后在显示可用于客户的CatalogItems列表时使用:

 select * from CatalogItems ci where (ci.customerId is null or ci.Customerid = @customerid);

当前系统使用0作为CustomerId来标记它对所有客户都可用,但是对我来说这不是标准的。

1 个答案:

答案 0 :(得分:1)

我相信这些设计都可以。重要的是,一旦您选择要坚持的设计。在数据库中,我每天都会使用许多不同的设计。有时有零,空值或1或-1表示对象是用于所有实体或不用于任何实体。也许还可以推断出另一种含义,该含义仅取决于数据库表的最初实现方式以及填充到该表中的数据是否符合原始设计。

所以我说“是”-当然可以。

您在问题中提到的设计是我的应用程序如何确定客户端默认值。这在我的应用程序的许多不同部分中使用。

例如-要显示所有客户可用的系统默认“目录项”:

SELECT * FROM CatalogItems ci WHERE ci.customerId is null;

要查找特定客户的自定义“目录项”:

SELECT * FROM CatalogItems ci WHERE ci.customerId = @customerid;

正如您所指出的,如果您想为客户找到所有可用的“目录项”:

SELECT * FROM CatalogItems ci WHERE ci.customerId is null or ci.Customerid = @customerid;