在使用数据库时,是否有时候使用一对一关系是有意义的?

184

我最近在思考规范化问题,但我发现我无法想象出数据库中应该存在1:1关系的情况。

  • 姓名:社会安全号码(SSN)? 我会将它们放在同一个表中。
  • 人员ID:地址ID? 同样,放在同一个表中。

我可以举出无数个1:多或多:多(带有适当的中间表)的例子,但从未碰到过1:1的情况。

我是否漏掉了一些明显的东西?


当数据库像这样分离时,将其拆分成多个物理设备会更容易。 - Pacerier
还有一个后续问题,如果有意义的话,如何做到呢?可以参考这里和这里。我的问题是如何选择哪个表具有外键约束?我猜这取决于你要解决什么用例... - Nate Anderson
26个回答

1
在我看来,1:1的关系将一个类的继承映射到RDBMS上。有一个包含通用属性的A表,即父类状态。每个继承类状态都与一个B表在RDBMS上进行了1:1的关联,该表包含专业属性。名为A的表还包含一个“类型”字段,表示“转换”功能。
再见, Mario

0

它不是为了安全目的而存在,但有更好的方法来进行安全检查。想象一下,您创建了一个仅能打开一个门的钥匙。如果这个钥匙可以打开其他任何门,那么您应该发出警报。本质上,您可以拥有“CitizenTable”和“VotingTable”。公民选出候选人并存储在投票表中。如果公民再次出现在投票表中,则应发出警报。请注意,这是一对一的关系,因为我们不是指候选人领域,而是指投票表和公民表。

例子:

 Citizen Table
 id = 1, citizen_name = "EvryBod"
 id = 2, citizen_name = "Lesly"
 id = 3, citizen_name = "Wasserman"

 Candidate Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"

那么,如果我们把投票表格看作是这样的:

 Voting Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"
 id = 4, citizen_id = 3, candidate_name = "Hill Arry"
 id = 5, citizen_id = 3, candidate_name = "Hill Arry"

我们可以说,公民号码3是一个撒谎的骗子,欺骗了伯恩·尼。这只是一个例子。

0

当你处理来自第三方产品的数据库时,你可能不想更改他们的数据库以防止紧密耦合。但是你可能有与他们的数据一一对应的数据。


0

如果你追求规范化,1:1关系并没有太多意义,因为任何1:1的内容都可以保存在同一张表中。

但在现实世界中,情况常常不同。你可能需要将数据拆分以匹配应用程序接口。


我不同意“一张表格理论”。在某些情况下,超类型子类型关系最好用1:1的关系来表达。 - Michael Riley - AKA Gunny
1
实际上,如果你走极端的规范化路线,那么你会有更多的一对一关系。Date提出的早期规范化形式包括不允许任何列为空的规则。这意味着,如果一个表的某个列可能为空,则应该放在自己的表中,并且只有在有值时才添加行。这个规则大多已经被废弃,包括Codd在内。 - Tom H

0

如果您的数据库中有某种类型的对象,则可能需要使用。

假设在表T1中,您有列C1、C2、C3...,并且它们之间存在一对一关系。这是可以的,因为它处于规范化形式。现在假设在表T2中,您也有列C1、C2、C3...(名称可能不同,但类型和角色相同),并且它们之间也存在一对一关系。出于与T1相同的原因,T2也是可以的。

然而,在这种情况下,我认为应该使用单独的表T3,其中包含C1、C2、C3...,并且从T1到T3以及从T2到T3之间存在一对一关系。如果已经存在另一个表,其中已经存在一对多的C1、C2、C3...,例如从表A到表B的多行,则更适合使用B,从T1到B具有一对一关系,从T2到B也是如此,并且仍然存在从A到B的相同的一对多关系。

我认为规范化不符合这个想法,并且可能是一个超出规范化范围的概念:识别对象类型并将同一类型的对象移动到它们自己的存储池中,使用一对一关系从某些表中,以及一对多关系从其他一些表中。

-4

任何时候,两个完全独立的实体之间存在一对一的关系。这里有很多例子:

人 <-> 牙医 (它是1:N,所以是错误的!)

人 <-> 医生 (它是1:N,所以也是错误的!)

人 <-> 配偶 (它是1:0|1,所以大多数情况下是错误的!)

编辑: 是的,那些都是相当糟糕的例子,特别是如果我总是在寻找一个1:1,而不是在任一侧上是0或1。我想我的大脑出了点问题 :-)

所以,我再试一次。经过一番思考,结果发现,只有当它们在更高的分类中一起存在时,你才能拥有两个必须(就软件而言)始终在一起的单独实体。然后,只有当你降解到较低的层次时,这些事物才是分开的,但在更高的层次上,它们不能没有彼此。因此,上下文是关键。

对于医学数据库,您可能希望存储有关身体特定区域的不同信息,并将其作为单独实体保留。在这种情况下,患者只有一个头部,他们需要拥有它,否则他们就不是患者(他们还有一个心脏和其他必要的单个器官)。如果您想跟踪手术,那么每个区域应该是一个独特的单独实体。

在生产/库存系统中,如果您正在跟踪车辆的组装,则肯定希望将发动机进度与汽车车身区分开来,但二者之间存在一对一的关系。汽车必须有一个发动机,而且只能有一个(否则它就不再是“汽车”了)。发动机属于唯一的一辆车。

在每种情况下,您可以将单独的实体生成为一个大记录,但考虑到分解的程度,这是错误的。在这些特定上下文中,它们是真正独立的实体,尽管在更高的层次上可能看不出来。

保罗。


牙医只有一个病人吗?医生也只有一个病人吗?如果你把一个配偶放在一张桌子上,另一个配偶放在另一张桌子上,那么这个人只跟他/她的配偶一对一交流。(我本来想说男的在一桌,女的在另一桌。算了吧) - Mark Brady
马克,你可以只创建一个“配对”表,使得行总是成对出现。但除此之外,我同意你的,呃...发泄。:P - JohannesH
是的,我也同意马克的观点。 :-) (我可以自嘲一下我的愚蠢回答吗?) - Paul W Homer
是的,坦承自己的“愚蠢”表明你有多聪明。真正的懦夫会删除他们愚蠢的回答……幸好他们不是医生,否则删除病历就麻烦了。实际上,我们也最好不要是医生;重启会是一种糟糕的医疗治疗。 - Mark Brady
我竟然可以删除它?:-) - Paul W Homer
3
我一直认为,即使是世界上最聪明的人(无论此时此刻是谁)也会有犯傻的时候。这是人类的诅咒 :-) 然而我的电脑却有近乎智能的时刻。 - Paul W Homer

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