使用类型/子类型数据模型处理外键的最佳方法是什么?

问题描述

我必须为一组(有限的)产品创建一个数据库结构,这些产品具有一些共同的属性和许多不同的属性。我创建了一个Product表/类型,并为每个子类型(CarBike)创建了一个单独的表。 product的外键引用在每个子类型中具有唯一约束(一对一关系),并且在该子类型中也用作主键。

我必须以其他方式引用其他表中的产品,以使目标表可以包含任何一种产品类型。例如,有一个合同表,其中产品作为外键。它可以是任何子类型(CarBike等)。我应该如何为这些外键建模?

我有两个解决方案。我可以在没有FK约束的合同表中创建引用,也可以添加一个字段以保存到产品的子类型(多态关联)。但是我必须在很多地方引用该产品。恐怕这种方法在广泛使用时会造成无法维护的混乱。

第二种解决方案是,我仅在每个关系中引用产品超类型,并从超类型访问子类型属性,因为每个超类型记录将只有一个子类型记录。

从长远来看,我想知道第二种方法的可管理性如何?当我在查询产品表时还需要获取子类型的属性时,联接表的最佳方法是什么?

解决方法

我将使用第二种方法,并在通常需要引用“产品”(而不是特定产品类型)的地方创建product表的外键。

如果您在查询时确实需要其他特定于子类型的属性,例如contract表中,您始终可以联接到子类型表或在单独的查询中检索其他属性。这取决于您在只需要“产品”的上下文中需要特定属性的频率。

根据对产品特定属性的要求,可能需要考虑完全放弃子类型表,并将特定类型的属性存储在jsonb表的product列中。如果您对数据类型检查或一组固定的(受控制的)附加属性有非常严格的要求,那么显然这是行不通的。

,

经常会问到这样的问题,尽管通常这些子类型是特定于手头的情况。

您可以查看我的常用答案here 注意我使用的术语是超类/子类。

您的方法类似于类表继承。

一种值得一看的技术是共享主键。子类没有自己的ID字段。而是使用超类表的Id字段的副本。此副本可以用作返回超类表的外键,也可以作为子类表的主键。这使某些联接变得简单,容易和快速。