一对多连接表以避免可空列

时间:2016-04-10 21:29:06

标签: sql-server database-design

我想知道自己是不是第一个在这个问题上苦苦挣扎的程序员,但是我无法在这方面找到任何关于此事的内容。

我的问题是,制作一对多连接表是个好主意,以防止NULL引用。

让我们解释一下,在我们的业务需求中,我们有一些活动导致付款,即销售,贷款,租金,服务等。每项活动可以有零个或一个或多个付款。

在设计数据库时,我们有每个活动的表格,销售 - 贷款 - 租金 - 服务等,以及付款表。活动和付款之间的关系是一对多,每笔贷款可以有很多付款,每笔租金可以有很多付款。

但是存在问题,每笔付款可以是贷款,销售或任何其他活动,我们需要将其与相应的活动联系起来。我想有两个选择:

1)在Payments表中为每种活动添加一些外键,LoanID - RentID - ServiceID等。并使它们为Nullable,因为贷款既不是服务也不是租金。

我个人不喜欢这个解决方案,它非常容易出错,因为它是Nullable,人们很容易忘记添加匹配的FK,然后我们就不知道这笔付款是什么了,我们失去了参照完整性。尽管可以通过创建一些约束来确保存在多于或少于一个FK,但是创建正确的约束并考虑所有可能的选项并不容易,并且很难重新创建。添加新FK列时的约束。

不用说这种表的丑陋。不要谈论在表格中放置不必要的可空列的主要问题。

2)第二种解决方案,用于为每种活动创建连接表,称为活动付款,即LoanPayments等,其中包含活动ID和付款ID,如“多对多”表格。

上面没有上述问题,每次付款都与其对应的活动有关,没有参照完整性丢失,没有Nullable列。 但问题是它扩大了数据库,并在表之间添加了另一层,并且在加入查询时需要更多工作。

有人知道吗?

3 个答案:

答案 0 :(得分:3)

另一个选择是创建一个超类型表,比如Activity,它包含所有常见属性:

enter image description here

这应该保持表的数量很小,并且仍然允许您识别付款的活动类型。请注意,这假设不同活动之间存在共同属性。如果不是这种情况,您列出的第二个选项可能就是这样。

答案 1 :(得分:1)

在SO中查找以下标记。

这些标签上的信息标签为您提供了简要说明,标签下分组的问题将为您提供一些示例。

单表继承与您提供的解决方案类似,并且您不满意。是的,确实涉及NULLS。通常,应用程序会阻止此处的用户错误。

类表继承就像AMS提供的解决方案。请注意,SalesID和LoanID同时列为PK和FK。这暗示了共享主键的技术。有了这个,SalesID和LoanID是ActivityID中值的副本。同样,它是应用层,它做了必要的工作,以确保副本是正确的。

答案 2 :(得分:0)

在这种特定情况下(不一定适用于类似的情况),我们通常在视图/功能中动态计算每次付款的时间(按时间顺序)

在其他情况下,我们有一个销售表,其中每个产品可以是实体产品或服务或任何其他付费优惠。这样就可以将所有借记交易限制在一个tbale HTA