何时使用数据库表之间的一对一关系?

22
一个数据库设计问题:什么时候决定使用一对一的关系表?
举个例子,当你有用户(User)和用户资料(UserProfile)表时,人们会将它们分开而不是把所有列都放在一个用户表中。
从技术上讲,由于它们之间的关系是一对一,你可以只在一个表中放置所有列。
我知道有人说,对于UserProfile表,随着时间的推移,你需要修改表来添加更多列,但我真的不认为这是将表拆分的充分理由。
因此,如果我要设计一个用户表和用户资料表,是否最好将它们放在一个表中?

可能是在数据库中使用1:1关系是否有意义的时候?的重复问题。 - Tripartio
8个回答

17

我只在想要让一个对象多态地属于多个对象时才使用1对1关系。

例如,像地址这样的东西。用户有一个地址,企业有一个地址,精选餐厅也有一个地址。所有实例都在同一张表中处理,并且具有相同的代码来管理它。将其数据模型重构以便在其他位置重复使用。


10

考虑如何设计业务对象。你是要在一个User对象上拥有50个属性,还是只在User对象中包含少量的详细属性,然后再创建一个Profile对象来包含其他个人资料数据?

当表中的数据相关但用途不同时,应该使用一对一关系。(可能需要更好的措辞)

同时,这样可以更容易地查找,比我讨厌的事情之一就是必须浏览具有75列的表。


9
经典原因是为了避免可空列。
在列中有一个NULL值可能会使编写清晰(可维护)的SQL更加困难。@Ovid这里写到了这一点,参考了Chris Date的工作。

+1 很好的答案。从应用程序开发者的角度来看,我仍然会倾向于接受空值并使用像NHibernate这样的好的ORM。 - Iain Holder

7

只有当用户表中的所有记录都不需要UserProfile表中的字段时,才应该将它们拆分开来。例如,如果您有300万个用户,但其中只有3000个具有UserProfiles,则将它们拆分开可能是有意义的(以避免大量的空列)。

尽管现在随着数据库速度的提高和存储成本的降低,出于这个原因将它们拆分开来并没有太大的区别......


3
我最近看到一个例子,其中有一张表格包含大部分数据,另一张表格包含大量可选数据。
第二个表格只有三分之一的行数,但是列数是第一个表格的三倍。
几年前这样做是为了避免列中的大量空值 - 即空白处。
然而,如果你现在这样做,我建议不要费那个劲。接受空白的地方吧。这样做可能会给应用程序开发带来很多麻烦,而空间比开发时间更便宜。

3

这是从今天在本帖子中出现的另一个问题直接复制并粘贴的内容,但它在这里也很有用。是否有时使用数据库1:1关系是有意义的?

我主要使用它们有几个原因。一是数据变化速率的显著变化。我的一些表可能有审计跟踪,我跟踪记录的先前版本,如果我只关心跟踪10列中的5个列的先前版本,那么将这5个列拆分到一个带有审计跟踪机制的单独表中更有效率。此外,我可能有一些记录(例如会计应用程序),这些记录只能进行写入操作。您无法更改美元金额或其所属的帐户,如果出现错误,则需要创建相应的记录以调整不正确的记录,然后创建更正条目。我对强制执行表上的约束有限制,以确保它们不能被更新或删除,但是我可能有几个对象属性是可塑的,这些属性保存在一个没有修改限制的单独表中。我再次这样做的另一个时间是在医疗记录应用程序中。与访问相关的数据一旦签名就不能更改,而与访问相关的其他数据可以在签名后更改。在这种情况下,我会拆分数据并在锁定表上放置触发器,在签名后拒绝更新锁定表上的更新,但允许对医生未签名的数据进行更新。
另一个评论者提到1:1不是标准化的,但在某些情况下,特别是子类型时,我不同意这种说法。比如说我有一个员工表,主键是他们的社会安全号码(这只是一个例子,让我们把这是否是一个好的键的争论留给另一个线程)。员工可以是不同的类型,例如临时或永久性的,如果他们是永久性的,则有更多的字段需要填写,例如办公电话号码,如果类型='永久性',则应该为非空。在第三正常形式数据库中,列应仅取决于键,即员工,但实际上它取决于员工和类型,因此1:1关系在这种情况下是完全正常的,并且是可取的。它还可以防止过度稀疏的表,如果我有10个通常填充的列,但有20个其他类型的列。

2

这个问题已经解决了,但我想补充一点说明,因为这对我来说不是很明显,也没有明确说明。1对1的关系并不意味着表A中的每个记录都有1个对应的表B中的记录。相反,它意味着对于表A中的每个记录,在表B中将会有0或1个对应的记录。

Shane D.和其他人描述了利用这个事实的情况。


0

我认为Shane D有一个相当有效的理由。因为我自己也遇到了同样的情况,一个拥有约40列的表格,这些列的数据是通过csv上传的,仅用于报告目的,并且有一组列来处理那些经常更新的文件。

因此,如果我们维护一个表作为解决方案。我们会频繁地对该表进行更新,但只会更新其中的5列,而不是50列。 我觉得每次更新都会干扰行分配,并且很可能会出现行链接,所以为了避免行链接,我采用基于DML活动的数据分离方法。

如果有更好的解决方案,请让我知道。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接