建模“一对一或两”关系

时间:2012-07-22 13:45:20

标签: mysql database database-design relational-database

我有一个不常见的数据库设计问题我不确定如何正确处理。有一个名为profile的表存储网站用户的公开个人资料信息。但是,每个配置文件都可以属于一个人或一对,所以我需要一个名为person的附加子表来存储特定于人的数据。每个profile实体必须至少有一个但不超过两个person子实体。

建立这种关系的最佳方式(就“犹太教”和/或表现而言)是什么?我应该使用常规的一对多并以编程方式或使用存储过程强制执行子项数量吗?或者我应该只在父表中创建两个外键字段,并允许null为其中一个?也许还有另一种我无法想到的方式?

修改:回应戈登问题的其他信息

  • 一个人只能与一个个人资料相关,而且没有一个人没有个人资料。也许名称person令人困惑,因为它可能表明一个人有个人资料,而实际上这是个人信息的个人资料。
  • 如果是夫妻档案,两个人都是平等的。由于网站的具体情况,2的限制永远不会改变,但是应该可以添加或删除一个人(使一个人的个人资料成为一个简介,反之亦然)但是永远不会少于1个或更多2人。
  • 如果没有配置文件数据,将永远不会提取人员数据,但有时可以在没有人员数据的情况下获取配置文件数据。

2 个答案:

答案 0 :(得分:3)

1)

有两个字段的解决方案:

  • PRO:允许您精确限制每个proflie的最小和最大人数。
  • CON:允许无档案的人。
  • CON:需要2个索引(每个字段1个)才能有效地获取给定人员的个人资料,占用额外空间并可能减慢INSERT / UPDATE / DELETE。

2)

但是如果你愿意在应用程序级别强制执行最小数字,那么最好用这样的东西:

enter image description here

CHECK(PERSON_NO = 1 OR PERSON_NO = 2)

特性:

  • CON:允许无人简介。
  • PRO:限制每个配置文件的最大人数,但只需修改CHECK即可轻松更改。
  • PRO:如果你保持上面的识别关系,它不需要额外的索引,并且是clustering - 友好的(相同配置文件的人可以物理地靠近在一起存储,最小化JOIN期间的I / O)

另一方面,如果你有一个密钥PERSON_ID(或类似的),那么{PROFILE_ID,PERSON_NO}上的附加索引也是有效执行这些字段上的密钥约束所必需的。

3)

从理论上讲,您甚至可以将这两种方法结合起来,避免 无人简介的人和无人简介:

enter image description here

(PERSON1_ID不能为空,PERSON2_ID可以为空)

然而,这会导致循环引用,需要延迟约束来解析,遗憾的是MySQL不支持这些约束。

4)

最后,您可以采用蛮力方法,只需将两个人的字段放在配置文件表中(并使其中一个集合不能为NULL,另一个为NULL)。


在所有这些可能性中,我可能会选择2)。

答案 1 :(得分:1)

正如您在问题中提到的,您基本上有两个选项。您可以在表中存储两个字段。或者,您可以拥有第二个包含映射信息的表。

以下是一些可以帮助您回答问题的其他问题:

  • 一个人可以拥有自己的个人资料和个人资料吗?
  • 个人在个人资料中是“平等”还是一个人是“主人”而另一个人是“候补人”?
  • 当您获取个人资料信息时,您是否始终会在个人资料中包含有关所有人的信息?
  • 你能有没有个人资料的人吗?

在这种情况下,我只是狡猾地怀疑“2”的限制将来可能会改变。这表明将映射存储在单独的表中,因为通过添加字段来增加“2”在修改现有代码方面是个问题。换句话说,创建一个单独的表,person-profile,将人员映射到配置文件。在mysql中,您始终可以使用GROUP_CONCAT()收集人员级别的信息。

最好将这样的相似字段放在同一个表中的情况是一个明显优先,另一个是备用。在这种情况下,你正在做很多“合并(,)”类型的逻辑。