很抱歉这个菜鸟问题,但是是否真的需要对数据库中的表使用一对一关系?您可以在一个表中实现所有必需的字段。即使数据变得很大,您也可以在SELECT
语句中枚举所需的列名,而不必使用SELECT *
。您何时真正需要这种分离?
很抱歉这个菜鸟问题,但是是否真的需要对数据库中的表使用一对一关系?您可以在一个表中实现所有必需的字段。即使数据变得很大,您也可以在SELECT
语句中枚举所需的列名,而不必使用SELECT *
。您何时真正需要这种分离?
Answers:
父类和子类之间的“ 1至0..1”用作实现继承的“单独表中的所有类”策略的一部分。
可以在单个表中表示“ 1到0..1”,其中“ 0..1”部分覆盖可空字段。但是,如果关系主要是“ 1到0”而只有几行“ 1到1”,则将“ 0..1”部分拆分为单独的表可能会节省一些存储(和缓存性能)的好处。一些数据库在存储NULL方面比其他数据库更为节俭,因此使该策略可行的“临界点”可能会有很大差异。
实际的“ 1对1”会垂直分割数据,这可能会影响缓存。数据库通常在页面级别而不是在单个字段级别上实现缓存,因此,即使您仅从一行中选择了几个字段,通常也将缓存该行所属的整个页面。如果一行很宽,并且所选字段相对较窄,那么您最终将缓存很多实际上不需要的信息。在这种情况下,垂直分区数据可能很有用,因此仅缓存较窄,更频繁使用的部分或行,以便将更多的部分或行放入缓存中,从而使缓存有效地“更大”。
垂直分区的另一种用途是更改锁定行为:数据库通常无法锁定单个字段的级别,只能锁定整个行。通过拆分行,您只允许在锁的一半上进行锁定。
触发器通常也是特定于表的。从理论上讲,您只能有一个表,而触发器却忽略了该行的“错误的一半”,但是某些数据库可能会对触发器可以做什么和不可以做什么施加了额外的限制,这可能使这变得不切实际。例如,Oracle不允许您修改变异表-通过具有单独的表,只有其中一个可以变异,因此您仍然可以从触发器中修改另一个。
单独的表可以提供更精细的安全性。
这些注意事项在大多数情况下都是无关紧要的,因此在大多数情况下,您应考虑将“ 1对1”表合并为一个表。
我的2美分。
我在一个所有人都在一个大型应用程序中进行开发的地方工作,并且所有内容都是一个模块。例如,我们有一个users
表,我们有一个为用户添加Facebook详细信息的模块,另一个向用户添加Twitter详细信息的模块。我们可以决定拔出其中一个模块,并从我们的应用程序中删除其所有功能。在这种情况下,每个模块都将自己的表以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 ...)
最明智的使用时间是,如果有两个单独的概念仅以这种方式联系在一起。例如,一辆汽车只能有一个当前的驾驶员,而驾驶员一次只能驾驶一辆汽车-因此,汽车和驾驶员的概念之间的关系为1比1。点。
另一个原因是您想以不同的方式来专门化一个概念。如果您有一个Person表,并想添加不同类型的Person(例如Employee,Customer,Shareholder)的概念,则每个人都需要不同的数据集。它们之间相似的数据将在“人员”表上,专家信息将在“客户”,“股东”,“雇员”的特定表上。
一些数据库引擎难以有效地将新列添加到非常大的表(许多行)中,并且我已经看到扩展表用于包含新列,而不是将新列添加到原始表中。这是附加表的更可疑用法之一。
您可能还决定将单个概念的数据划分为两个不同的表,以解决性能或可读性问题,但这是一个相当特殊的情况,如果您是从头开始的话-这些问题将在以后显示。
您指的是数据库规范化。我可以在我维护的应用程序中想到的一个示例是Items。该应用程序允许用户出售许多不同类型的项目(即InventoryItems,NonInventoryItems,ServiceItems等)。虽然我可以将每个物料所需的所有字段存储在一个物料表中,但要维护一个基本物料表要容易得多,该物料表包含所有物料共有的字段,然后针对每种物料类型(例如,库存,非库存,等。)包含仅适用于该项目类型的字段。然后,项目表将有一个外键指向它表示的特定项目类型。特定项目表和基础项目表之间的关系将是一对一的。
下面是有关规范化的文章。
在实践中,我通常会遇到两种一般的1:1关系:
IS-A关系,也称为超类型/子类型关系。这是当一种实体实际上是另一种实体(EntityA IS A EntityB)的类型时。例子:
在所有这些情况下,超类型实体(例如Person,Item或Car)将具有所有子类型共有的属性,并且子类型实体将具有每个子类型唯一的属性。子类型的主键将与父类型的主键相同。
“老板”关系。这是一个人是组织单位(部门,公司等)的唯一老板或经理或主管的情况。当只允许一个老板担任组织单位时,代表老板的人实体与组织单位实体之间存在1:1的关系。
首先,我认为这是一个建模和定义组成独立实体的问题。假设您只有customers
一个,只有一个address
。当然,您可以在一个表中实现所有功能customer
,但是如果将来允许他使用2个或更多地址,则需要对其进行重构(不是问题,而是要有意识地做出决定)。
我还可以想到一个有趣的案例,在其他答案中没有提到,在这种情况下,拆分表可能很有用:
再次想像,您每个人customers
只有一个address
,但是这次有一个地址是可选的。当然,您可以将其实现为一堆NULL
可用的列,例如ZIP,state,street
。但是,假设您确实有一个地址,则状态不是可选的,而ZIP是。如何在单个表中建模?您可以在customer
表上使用约束,但是将其划分到另一个表中并使其foreign_key可为空则要容易得多。这样一来,您的模型就可以更明确地说明该实体 address
是可选的,而则该实体是该实体ZIP
的可选属性。