【发布时间】:2012-02-12 07:50:18
【问题描述】:
多态关联(PA's)对于一个相对简单的数据库需求来说是相当多的:让不同的表在一个共享表中具有子记录。经典示例是一个包含评论记录的单个表,这些评论记录适用于不同的不一定有亲属关系的实体。
在this question 中,Mark 表现出色,展示了实现 PA 的三种常用方法。我想使用基表方法,在同样出色的answer by Bill Karwin 中有更详细的描述。
具体示例如下所示:
实体的主键引用基表中相同的键值,注释表引用基表,因此遵守参照完整性。这里的关键部分是实体表的主键具有不同的域。它们是通过在基表中创建新记录并将其生成的键复制到实体的主键来生成的。
现在我的问题是:如果我想在现有数据库中引入具有参照完整性的 PA,该数据库的实体会生成自己的相互重叠的主键,该怎么办?
到目前为止,我看到了两个选项:
选项 1:
每个实体都有自己的主键,但也有一个备用键。
喜欢:
- 接近推荐的方法。
- 基表稳定。
不喜欢:
- 必须修改现有实体。
- 很难找到评论的拥有实体。
选项 2:
每个实体在基表中都有自己的外键列。这看起来像 Mark 的多列方法。
喜欢:
- 现有实体不受影响。
- 很容易找到评论的所属实体。
不喜欢:
- 稀疏列
- 基表不稳定:引入带有 PA 的新实体时需要修改
我倾向于选项 1,可能在基表中使用字段“EntityName”进行双向查找。 哪个选项会更好。或者是另一种更好的方法?
【问题讨论】:
-
选项 1 更容易维护。如果您必须继续向基表添加列,这将是一件麻烦事,并且由于页面拆分和指针等原因需要大量维护。
-
@JNK 好点,要记住物理存储影响很重要。
-
您可以使用选项 1,但不能使用额外的代理备用键。新的备用键可以是现有的主键(每个实体的),用
EntityType列扩展(比如CHAR(1),这将是E用于事件,P用于人员,D用于产品) -
对现有实体的唯一修改是添加持久列和唯一约束。
-
是的,
Event的 FK 将是FOREIGN KEY (EntityType, EventID) REFERENCES Entity (EntityType, EntityID)。见:Option 3 in @gbn's answer
标签: sql-server-2008 database-design refactoring polymorphic-associations