其他回答者所说的,再加上以下关于子类表的主键的内容。
你的情况看起来像是一种设计模式,被称为“泛化特殊化”,或简称为Gen-Spec。如何使用数据库表建模gen-spec的问题在SO中经常出现。
如果你正在使用Java等面向对象编程语言进行gen-spec建模,你将使用子类继承功能来处理细节。你只需定义一个类来处理通用对象,然后定义一组子类,每个专门对象类型对应一个子类。每个子类都继承通用类。这很容易和直接。
不幸的是,关系数据模型没有内置子类继承,SQL数据库系统也没有提供此类功能,据我所知。但你还没有倒霉。你可以设计你的表以在结构上与OOP的类结构相似地建模gen-spec。然后,当新项目添加到通用类时,您必须安排实现自己的继承机制。详情请见下文。
班级结构相当简单,有一个表用于通用类,每个特殊子类都有一个表。以下是Martin Fowler网站上的一个很好的说明
Class Table Inheritance.。请注意,在此图中,Cricketer既是子类又是超类。您必须选择哪些属性放在哪个表中。该图显示了每个表中一个样本属性。
棘手的细节是如何为这些表定义主键。通用类表以通常的方式获得主键(除非此表是另一个泛化的专业化,例如板球手)。大多数设计师给主键一个标准名称,例如“Id”。他们使用自动编号功能来填充Id字段。特定类表获得一个主键,可以命名为“Id”,但不使用自动编号功能。相反,每个子类表的主键都受到约束,以引用广义表的主键。这使得每个专门的主键都成为外键和主键。请注意,在板球手的情况下,Id字段将引用Players中的Id字段,但Bowlers中的Id字段将引用Cricketers中的Id字段。
现在,当你添加新的项目时,你必须维护引用完整性。以下是具体方法。
首先,在gen表中插入一行新数据,并提供除主键之外的所有属性数据。自动编号机制将生成一个唯一的主键。接下来,在适当的spec表中插入一行新数据,包括所有属性数据,其中包括主键。你使用的主键是刚刚生成的全新主键的副本。这种主键的传播可以称为“穷人的继承”。
现在,当你想要从一个子类中获取所有广义数据和所有特定数据时,你只需要通过公共键连接这两个表。所有与所讨论的子类无关的数据都将从连接中删除。这很简单、快速、有效。