连接表以获取与多对多连接关联的表的子项的子集

时间:2011-01-04 18:10:02

标签: database-design

我有一个多对多关系的标准连接表,其主键是两个字段的复合键。这两个字段是每个连接表的ID。

其中一个联接表在另一个表中有多个子项。标准的一对多关系。

这一切都很好。但是现在我想指定这些孩子的子集并将它们与多对多关系远端的表相关联。具体来说:


表:赛马场
PK: ID

表:马厩
PK: ID

表: StablesToRaceCourses
PK是两个外键的复合键:
     RaceCourseID
    的 StableID

表:马匹
PK: ID
FK: StableID


一切都很好 - 一匹马属于一个马厩,一个马场可以进入一些马厩。但困难的部分是:每个RaceCourse都可以从一个可以进入的马厩中选择一匹马。因此,理想情况下,这个新表只允许Horses与RaceCourse相关联,RaceCourse已经与Horse's马厩相连。

类似的东西:

表: HorsesForRaceCourses
FK: RaceCourseID 链接到StablesToRaceCourses.RaceCourseID
FK: StableID 指向StablesToRaceCourses.StableID的链接 FK: HorseID 链接到Horses.ID

其中PK是3个外键的组合。这看起来合情合理吗?我正在使用MS Access,但它不会强制我的参照完整性,说“找不到主表的引用字段的唯一索引”。我可以通过从这个表中删除StableID(并直接链接到RaceCourse)来实现这一点,但是我需要依赖应用程序逻辑来确保RaceCourse不与Horse相关联,除非RaceCourse已经与Horse的Stable相关联。也许我要求太多的数据库为我强制执行此操作?

2 个答案:

答案 0 :(得分:2)

这是一个非常好的问题。

有一个非常非常好的理由让数据库尽可能多地执行关系。但是数据库的声明性质是有限的。假设您有一个员工表和一个orgunit表。 Orgunit可以拥有许多员工,但最多只有一名员工也有类型的主管。世界上最简单的事情是以声明的方式做。

您所描述的是概念上称为“协会”的东西。想想视频,商店和客户。 < - OMG即1990年代。一家商店有很多电影。一家商店有很多顾客。在某些时候,“租户发生在客户A,从商店C租用电影B.租赁表有三个PK。该租赁表还有一个日期,到期日,支付费用等。

来自PowerDesigner文档

  

在Merise建模方法中,关联用于连接多个实体,每个实体代表明确定义的对象,但是由事件链接,事件可能无法由另一个实体清楚地表示。

在你的情况下,“选择”就是那个事件。 “RaceCourse可以选择”

在视频租赁示例中,客户和商店之间可能存在关联,并且只有“属于”该商店的客户才可以在那里租用。这个事实并没有改变我的租赁表。

好的,所以这不是你的情况的精确模拟,但你明白了。

从纯粹的造型角度来看,你拥有拥有多匹马的马厩,你有赛道可以使用多个马厩和马厩,适用于许多赛道。这是第三个正常事情的结束。

现在你有了一个叫做选择的过程。如果我是你,我会把它建模为星型模式。

除了“事实”之外,我还会把所有三个键都放在一边。选择日期,日期选择开始,日期选择结束,合同#,日期稳定被通知等。这将使得很容易创建关于什么日期在哪里等等的马的报告...以及马是否会改变马厩这些信息将会反映出来,因为您包含了马厩的FK,而不是依赖于加入以找到它。

答案 1 :(得分:1)

我已经尝试过Access中的每一种方式,并且我确信“复合外键”在Access中不能像在SQL Server中那样工作。你可以设置它们,它们只是在这种情况下不起作用。我找不到这方面的实际来源,但在研究了我试图采用这种方法的数据库中的问题之后,我读了许多论坛帖子,表明老帽子知道要避免这种情况。

不要在任何可能需要外键引用的表上使用复合主键,而是使用单字段Autonumber主键,通常称为ID。但另外在作为你的PK的外键字段上添加一个多字段唯一索引。

这在功能上是等效的,虽然它有时意味着你需要在查询中加入更多的表来获得“真正的”外键。