在关系数据库中表达is-a关系

时间:2020-03-06 14:41:29  来源:igfitidea点击:

我想知道是否存在一种干净的方式来表示is-a关系,如本例所示:

该数据库存储三种类型程序的记录时间:电影,游戏节目,戏剧。从面向对象的角度来看,这些都是程序。这些子类中的每一个都有不同的属性。这是表格(fk前缀表示外键):

电影
ID
姓名
fk导演

游戏节目
ID
姓名
fkHost
fk选手

戏剧
ID
姓名

用面向对象的术语来说,记录表将看起来像这样:
记录
ID
fk程序
开始时间
时间结束

在不违反常规格式的情况下,我想到的唯一方法就是拥有三个记录表,分别是recordMovie,recordGameShow和recordDrama。

有没有办法在不违反数据库规范化原则的情况下将这些表合并为一个表?

以下是一些不起作用的示例,以说明此想法:

程序
ID
fkMovie
fkGameShow
fkDrama

该表违反了第一个范式,因为它将包含空值。对于每一行,这3个条目中只有一个将为非null。

程序
ID
fkSpecific fkMovie OR fkGameShow OR fkDrama
fkType将指示要查找的表

在这里,我将无法强制执行参照完整性,因为fkSpecific可能会指向三个表之一。

我只是想节省这里有3个而不是1个表的开销。也许这根本不适用于RDB。

解决方案

是的,应该像一张桌子

Programs:
   id,
   name,
   type_id,
   length,
   etc...

带有程序类型的参考表(如果有)
与该类型关联的其他数据位:

ProgramType
   type_id,
   type_name,
   etc...

像那样。

这是很多人以前面临的一个非常标准的问题,我们可能考虑的所有方法都可能是一次完成的。

一个简单的Google搜索就每个优点和缺点做了一些很好的解释。

我的第一个想法是使用一个Program表格来播放电影,电视节目和电视剧。然后添加一个ProgramType表,并使用一个外键,就像父帖子一样。

可以添加其他列,例如fkDirector,fkMovie。然后添加一个约束条件,当ProgramType是电影时,fkDirector不能为null,或者当它为节目时,fkHost不能为null。

这样可以轻松查找在开始日期和结束日期之间记录的所有电影/节目/...。同时确保所有数据均已填写并且引用正确。

有人有更好的主意吗?

为什么要将所有数据存储在一个表中?他们显然是不同的实体。我们对主Record表的想法,以及辅助recordMovie,recordGameShow和RecordDrama。

要在辅助表和主表之间强制执行" is-a"关系,我们需要在所有这些表中声明Record.id为外键,并为其添加约束,因此这是唯一的,它强制执行一个一对一的关系,将这些表转换为主表的扩展。

我们还需要在主"记录"表中添加一个新字段,以指示该记录是哪种记录(电影,游戏节目,话剧等)。这可以是对另一个表(RecordTypes?)的外键引用,也可以是字符串(具有可以接受的值定义的约束)。

这些都是关于该主题的好文章:
http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/
http://www.agiledata.org/essays/mappingObjects.html

我最终将要做的是。我的程序表将简单地是:

程序
ID

然后将fkProgram添加到每个子类(戏剧,游戏节目和电影)。这样,Program表将成为子类之间的中间表。我可以使用外键指向Program表,以引用任何子类的实例。这将使我只有一个Record表,而不会违反任何常规形式。

电影
ID
fk程序
姓名
fk导演

记录
ID
fk程序
开始时间
时间结束

用Google搜索"一般化专业化关系建模"。

" gen-spec"模型遵循与" is-a"关系相同的模式。

例如,汽车是专用车辆。卡车是另一种特殊的车辆。摩托车是第三类专用车辆。

我们应该找到很多文章。

有趣的是,如果我们只是在" gen-spec"上进行google搜索,则最重要的链接之一就是对Smalltalk中gen-spec建模的描述。