当我应该使用一对一的关系?

对不起,这个noob问题,但有什么真正的需要使用数据库中的表一对一的关系? 您可以在一个表内实现所有必要的字段。 即使数据变得非常大,您也可以在SELECT语句中枚举所需的列名,而不是使用SELECT * 。 你什么时候真的需要这种分离?

1到0..1

  • 超级类和子类之间的“1到0..1”被用作实现inheritance的 “分表中的所有类”策略的一部分。

  • 一个“1到0..1”可以用一个单独的表格来表示,其中“0..1”部分被可空字段覆盖。 但是,如果关系大部分是 “1到0”,并且只有几个“1到1”行,那么将“0..1”部分分割成单独的表可能会节省一些存储(和caching性能)的好处。 一些数据库比其他数据库更容易存储空值,所以这个策略变得可行的“切点”可能会有很大差异。

1至1

  • 真正的“1比1”垂直划分数据,这可能会影响caching。 数据库通常在页面级别实现caching,而不是在单个字段级别,所以即使从行中只select了几个字段,通常也会caching该行所属的整个页面。 如果一行很宽,而且所选的字段相对较窄,那么最终会caching许多您实际上不需要的信息。 在这种情况下,对数据进行垂直分区可能是有用的,所以只有更窄,更频繁使用的部分被caching,所以更多的caching可以放入caching,使caching“有效”。

  • 垂直分区的另一个用途是更改locking行为:数据库通常不能locking在单个字段的级别,而只能locking整个行。 通过分割这一行,你只允许在其中的一半上进行locking。

  • 触发器通常也是特定于表格的。 虽然理论上可以只有一个表,并且触发器会忽略该行的“错误的一半”,但是某些数据库可能会对触发器可以执行的操作和不能执行的操作施加额外的限制,从而使这种操作变得不切实际。 例如,Oracle不允许你修改变异表格 – 通过分开表格,只有其中一个变异,所以你仍然可以修改触发器中的另一个。

  • 单独的表格可能允许更细化的安全。

在大多数情况下,这些考虑是不相关的,因此在大多数情况下,您应该考虑将“1到1”表合并到一个表中。

如果一个表格中的数据与另一个表格中的数据相关,但不属于另一个表格中描述的实体,那么这是一个将其分开的候选人。

如果单独的数据也需要与其他实体相关,则这将在未来提供优势。

如果有两个单独的概念只会以这种方式联系起来,那么使用这个最明智的时机就是如此。 例如,一辆车只能有一个当前的司机,司机一次只能驾驶一辆车 – 因此,车与司机的概念之间的关系将是1比1.我接受这是人为的例子来certificate点。

另一个原因是你想用不同的方式来专门化一个概念。 如果你有一个Person表,并且想要添加不同typesPerson的概念,比如Employee,Customer,Shareholder – 每一个都需要不同的数据集。 他们之间相似的数据将在Person表上,专家信息将在Customer,Shareholder,Employee的特定表上。

一些数据库引擎很难有效地将一个新列添加到一个非常大的表(很多行),我已经看到用于包含新列的扩展表,而不是将新列添加到原始表中。 这是其他表格更可疑的用法之一。

您也可能决定将数据分为两个不同表格之间的单个概念,以获得性能或可读性问题,但是如果您从头开始,这是一个相当特殊的情况 – 这些问题将在稍后显示。

如果你把两个一对一的表放在一个表中,那么你可能会遇到语义问题。 例如,如果每个设备都有一个遥控器,那么将该设备和遥控器的特性串放在一张表中就不太好。 你甚至可能不得不花时间弄清某个属性是属于设备还是遥控器。

可能会出现这样的情况,当你的一半列将空置很长一段时间,或者永远不会被填满。例如,一辆车可能有一个拖车有一堆特点,或可能没有。 所以你会有很多未使用的属性。

如果您的表有20个属性,并且偶尔只有4个属性,那么为了解决性能问题,将表分成两个表是有意义的。

在这种情况下,把所有东西都放在一张桌子里是不好的。 此外,处理一个有45列的表格并不容易!

不经常。

如果你需要实现一些安全性,你可能会发现一些好处 – 所以一些用户可以看到一些列(table1),而不是其他的(table2)。

当然有些数据库(Oracle)允许你在同一个表中做这种安全性,但有些数据库可能不这样做。

与所有devise问题一样,答案是“这取决于”。

有几个考虑因素:

  • 桌子有多大(在场地和行方面)? 从维护和编程的angular度来看,把用户的名字,密码和其他不太常用的数据放在一起会很不方便

  • 组合表中具有约束的字段随着时间的推移可能变得繁琐。 例如,如果触发器需要触发某个特定的字段,则无论该字段是否受到影响,对于该表的每次更新都会发生这种情况。

  • 你们之间的关系将会是1:1? 正如这个问题所指出的那样,事情会变得很复杂。

另一个用例可以是:您可以从某个源导入数据并每天更新,例如关于书籍的信息。 然后,你自己添加关于一些书籍的数据。 那么将导入的数据放在另一个表中而不是自己的数据是有意义的。

您指的是数据库规范化。 我可以在我所维护的应用程序中想到的一个例子就是Items。 该应用程序允许用户出售许多不同types的项目(即InventoryItems,NonInventoryItems,ServiceItems等)。 虽然我可以将每个项目所需的所有字段存储在一个项目表中,但是维护一个基本项目表(包含所有项目通用的字段,然后为每个项目types分开表格)(例如库存,非库存,等)。其中包含专门只有该项目types的字段。 然后,项目表将具有它所表示的特定项目types的外键。 特定商品表和基本商品表之间的关系将是一对一的。

下面是关于正常化的一篇文章。

http://support.microsoft.com/kb/283878

我通常在实践中遇到两种一般的1:1关系:

  1. IS-A关系,也被称为超types/子types关系。 这是一种实体实际上是另一种实体(EntityA是一个实体B)的types。 例子:

    • 个人实体,在同一个公司内具有会计师,工程师,销售人员的独立实体。
    • 物品实体,具有Widget,RawMaterial,FinishedGood等单独的实体
    • 汽车实体,卡车,轿车等单独实体

    在所有这些情况下,超types实体(例如Person,Item或Car)将具有对于所有子types通用的属性,并且子types实体将具有对每个子types唯一的属性。 子types的主键将与超types的主键相同。

  2. “老板”关系。 这是当一个人是一个组织单位(部门,公司等)的独特的老板或经理或主pipe。 当一个组织单位只有一个上司允许时,代表上司的个人实体与组织单位实体之间存在1:1的关系。

在我编程的时候,我只遇到过这种情况。 当相同的两个实体(“实体A”和“实体B”)之间存在一对多和一对一的关系时。

当“实体A”具有多个“实体B”并且“实体B”仅具有一个“实体A”且“实体A”仅具有一个当前“实体B”而“实体B”仅具有一个“实体A”时。

例如,一辆车只能有一个当前的司机,司机一次只能驾驶一辆车 – 因此,车与司机的概念之间的关系是1比1. – 我从@Steve Fenton的答案中借用了这个例子

司机可以驾驶多辆汽车,而不是在同一时间。 所以Car和Driver实体是一对多或多对多的。 但是,如果我们需要知道当前的驾驶员是谁,那么我们也需要1对1的关系。

首先,我认为这是一个build模和定义什么是一个单独的实体的问题。 假设你有一个且只有一个address 。 当然,你可以在单一的customer实现一切,但是如果将来你允许他有两个或更多的地址,那么你需要重构这个(不是一个问题,而是一个有意识的决定)。

我还可以想到一个有趣的案例,在其他答案中没有提到,在这种情况下分割表格可能是有用的:

再想象一下,你们每个customers都有一个address ,但是这次有一个地址是可选的。 当然,你可以将其实现为一堆可以NULL列,比如ZIP,state,street 。 但假设你一个地址的状态是不是可选的,但ZIP是。 如何在单个表格中build模? 您可以在customer表上使用一个约束,但是在另一个表中分割并且使foreign_key可以为空是非常容易的。 这样,你的模型更加明确地说实体 address是可选的,并且ZIP是该实体的可选属性。

我的2美分。

我在一个大型应用程序开发的地方工作,一切都是模块。 例如,我们有一个users表,我们有一个模块为用户添加Facebook详细信息,另一个模块为用户添加Twitter详细信息。 我们可以决定拔掉其中一个模块,并从我们的应用程序中删除它的所有function。 在这种情况下,每个模块都将自己的表与1:1关系添加到全局users表中,如下所示:

 create table users ( id int primary key, ...); create table users_fbdata ( id int primary key, ..., constraint users foreighn key ...) create table users_twdata ( id int primary key, ..., constraint users foreighn key ...)