我想到标准化的那一天,对我而言,我想不起来数据库中应该存在1:1关系的时候了。
名称:SSN?我会将它们放在同一张表PersonID:AddressID中吗?同样,同一张桌子。
我可以拿出无数个1:1:1或many:many(带有适当的中间表)示例,但从来没有1:1。
我是否缺少明显的东西?
我想到标准化的那一天,对我而言,我想不起来数据库中应该存在1:1关系的时候了。
名称:SSN?我会将它们放在同一张表PersonID:AddressID中吗?同样,同一张桌子。
我可以拿出无数个1:1:1或many:many(带有适当的中间表)示例,但从来没有1:1。
我是否缺少明显的东西?
Answers:
1:1关系通常表示您出于某种原因对较大的实体进行了分区。通常是由于物理模式中的性能原因,但是如果期望同时有很大一部分数据“未知”,那么它也可能在逻辑端发生(在这种情况下,您有1:0或1:1,但没有更多)。
作为逻辑分区的示例:您拥有有关雇员的数据,但是当且仅当他们选择具有健康保险时,才需要收集更大的数据集。我会将有关健康保险的人口统计数据保存在不同的表中,以使安全分区更加容易,并避免在与保险无关的查询中拖拉这些数据。
物理分区的一个示例是将相同的数据托管在多个服务器上。我可能会将健康保险人口统计数据保持在其他状态(例如,HR办公室所在的位置),并且主数据库只能通过链接的服务器链接到该数据库...避免将敏感数据复制到其他位置,但仍可用于(在这里假设很少)需要它的查询。
每当您有需要较大实体的一致子集的查询时,物理分区就很有用。
原因之一是数据库效率。具有1:1关系可以使您拆分在行/表锁定期间将受影响的字段。如果表A具有大量更新,而表b具有大量读取(或来自另一个应用程序的大量更新),则表A的锁定将不会影响表B中的情况。
其他人提出了一个好观点。根据应用程序等如何攻击系统,安全性也是一个很好的理由。我倾向于采用不同的方法,但它可能是限制对某些数据的访问的简便方法。拒绝访问某个表确实很容易。
大多数排名靠前的答案都为1:1关系提供了非常有用的数据库调优和优化原因,但是我只想关注自然发生1:1关系的“野外”示例。
请注意大多数这些示例的数据库实现的一个重要特征:没有保留有关1:1关系的历史信息。也就是说,这些关系在任何给定时间点都是1:1。如果数据库设计人员希望记录关系参与者随时间的变化,则关系变为1:M或M:M;他们失去了1:1的本性。有了这样的理解,这里是:
“ IS-A”或超类型/子类型或继承/分类关系:当一个实体是另一实体的特定类型时,此类别。例如,可能有一个Employee实体,其属性适用于所有雇员,然后是不同的实体,以指示具有该雇员类型唯一的属性的特定雇员类型,例如Doctor,Accountant,Pilot等。此设计避免了多个null许多员工不会具有特定子类型的特殊属性。此类别中的其他示例可能是Product作为超类型,ManufacturingProduct和MaintenanceSupply作为子类型。动物是超型,狗和猫是亚型;请注意,每当您尝试将面向对象的继承层次结构映射到关系数据库中时(例如在对象关系模型中),这种关系就代表了这种情况。
“老板”关系,例如经理,董事长,总裁等,其中一个组织单位只能有一个老板,而一个人只能是一个组织单位的老板。如果适用这些规则,则您具有1:1的关系,例如部门的一位经理,公司的一位首席执行官等。“老板”关系不仅适用于人员。例如,如果只有一家商店作为公司总部,或者一个国家的首都只有一个城市,就会发生相同的关系。
某些稀缺的资源分配,例如,一次只能给一名员工分配一辆公司的汽车(例如,每名卡车司机一辆卡车,每辆出租车司机一辆出租车,等等)。一位同事最近给了我这个例子。
婚姻(至少在一夫多妻制是非法的法律管辖区):一个人一次只能与另一个人结婚。我从一本教科书中获得了这个示例,该示例将这用作公司记录员工之间婚姻的1:1一元关系的示例。
匹配的预留:进行唯一预留然后作为两个单独的实体实现时。例如,汽车租赁系统可能在一个实体中记录预订,然后在单独的实体中记录实际租赁。尽管可以将这种情况设计为一个实体,但分开实体可能是有意义的,因为并非所有预订都得到满足,并且并非所有租赁都需要预订,并且两种情况都非常普遍。
我重复我之前的警告,只有在没有历史信息记录的情况下,大多数都是1:1的关系。因此,如果员工改变了他们在组织中的角色,或者经理承担了另一个部门的责任,或者员工被重新分配了车辆,或者某人丧偶并重新结婚,那么关系参与者就可以改变。如果数据库未存储有关这些1:1关系的任何以前的历史记录,则它们将保持合法的1:1关系。但是,如果数据库记录了历史信息(例如为每个关系添加开始和结束日期),那么它们几乎全部变成了M:M关系。
历史注释有两个值得注意的例外:首先,某些关系发生变化,以至于很少有历史信息通常不会被存储。例如,大多数IS-A关系(例如产品类型)是不可变的。也就是说,它们永远不会改变。因此,历史记录点是没有意义的。这些将始终实现为自然的1:1关系。其次,由于预订和租赁是独立的事件,每个都有自己的日期,因此预订-租赁关系存储的日期分开。由于实体具有自己的日期,而不是1:1关系本身具有开始日期,因此即使存储了历史信息,这些实体仍将保持1:1的关系。
由于您的表达方式,您的问题可以用几种方式解释。响应显示了这一点。
在现实世界中,数据项之间肯定存在1:1的关系。毫无疑问。“是”关系通常是一对一的。汽车就是车辆。一车就是一车。一辆车可能是一辆车。有些车辆是卡车,在这种情况下,一辆车不是汽车。有几种答案解决了这种解释。
但是我认为您真正要问的是...当存在1:1关系时,是否应该拆分表?换句话说,您是否应该有两个包含完全相同的键的表?实际上,我们大多数人仅分析主键,而不分析其他候选键,但是这个问题略有不同。
1NF,2NF和3NF的规范化规则永远不需要将一个表分解(拆分)为具有相同主键的两个表。我还没有确定将模式放入BCNF,4NF或5NF是否会导致两个表具有相同的键。在我的头顶上,我会猜测答案是否定的。
有一个标准化级别称为6NF。6NF的规范化规则肯定会导致两个表具有相同的主键。6NF比5NF的优势在于可以完全避免NULLS。这对某些(但不是全部)数据库设计人员很重要。我从来没有费心将架构放入6NF。
在6NF中,丢失的数据可以由省略的行表示,而不是由某些列中具有NULL的行表示。
除了归一化表格以外,还有其他原因。有时拆分表会导致更好的性能。使用某些数据库引擎,通过对表进行分区而不是实际拆分表,可以获得相同的性能优势。这具有使逻辑设计易于理解的优点,同时为数据库引擎提供了加快工作速度所需的工具。
我主要出于一些原因使用它们。一是数据变化率的显着差异。如果我只想跟踪10列中的5个以前的版本,则我的某些表可能具有跟踪我在以前的记录版本的审计跟踪,将这5列分成一个单独的表并带有审计跟踪机制会更有效。另外,我可能有仅写的记录(例如会计应用程序)。您无法更改美元金额或所使用的帐户,如果输入有误,则需要创建相应的记录来写出调整错误记录的记录,然后创建更正条目。我在表格上有一些限制,以强制执行以下事实:无法更新或删除它们,但该对象可能具有一些可延展的属性,它们被保存在单独的表中,而不受修改的限制。我另一次这样做是在医疗记录应用程序中。存在与访问相关的数据,一旦签署就无法更改,而与访问相关的其他数据也可以在签署后更改。在那种情况下,我将拆分数据并在锁定表上放置触发器,以在签署时拒绝对锁定表的更新,但允许更新未签署医生的数据。
另一位发布者评论说1:1没有被标准化,在某些情况下,尤其是子类型化,我不同意这一点。假设我有一个employee表,并且主键是他们的SSN(这是一个例子,让我们保留一下对于另一个线程来说这是否是一个好键的争论)。员工可以是不同的类型,例如临时的或永久的,如果他们是永久性的,则他们需要填写更多字段,例如办公室电话号码,如果类型=“ Permanent”,则该字段不得为null。在第三范式数据库中,列应仅取决于键(即员工),但实际上取决于员工和类型,因此1:1关系是完全正常的,在这种情况下是理想的。它还可以防止表格过于稀疏,如果我通常填充10列,
我能想到的最常见的情况是当您拥有BLOB时。假设您要将大型图像存储在数据库中(通常,这不是最佳的存储方式,但是有时约束使其更方便)。您通常希望将Blob放在单独的表中,以改善对非Blob数据的查找。
就纯科学而言,是的,它们是无用的。
在实际数据库中,有时将很少使用的字段保留在单独的表中有时很有用:使用此字段和仅使用此字段可以加快查询速度;避免锁等
我还可以想到这样的情况:您拥有使用继承的OO模型,并且继承树必须持久化到数据库中。
例如,您有一个Bird和Fish类,它们都从Animal继承。在您的数据库中,您可以有一个“动物”表,其中包含动物类的公共字段,并且动物表与鸟表具有一对一关系,而与鱼具有一对一关系表。
在这种情况下,您不必具有一个Animal表,该表包含许多可为空的列来保存Bird和Fish属性,其中,当记录代表一只鸟时,所有包含Fish数据的列都设置为NULL。
相反,您在Birds表中有一条记录,该记录与Animal表中的记录具有一对一的关系。
这也是一种扩展已在生产中的表的方式,与“真实”数据库更改相比,该表具有更少(可感知)的风险。在传统系统中看到1:1的关系通常可以很好地表明在初始设计之后添加了字段。
我发现当我做1:1关系时,完全是出于系统原因,而不是关系原因。
例如,我发现将用户的保留方面放在1个表中,并将用户的用户可编辑字段放在不同的表中,可以使逻辑上更容易地编写关于这些字段的权限的规则。
但是您是正确的,理论上,1:1关系是完全人为设计的,几乎是一种现象。但是从逻辑上讲,它允许程序和优化程序更容易抽象数据库。
仅在某些情况下需要的扩展信息。在旧版应用程序和编程语言(例如RPG)中,程序是在表上编译的(因此,如果表更改,则必须重新编译程序)。在必须担心表大小的情况下,沿着文件标记也很有用。
对于1:1关系,我能看到的最好原因是数据库设计的SuperType子类型。我基于此模型创建了一个房地产MLS数据结构。有五种不同的数据供稿;住宅,商业,多户家庭,酒店和土地。
我创建了一个称为Type的SuperType属性,其中包含五个单独的数据提要中的每一个都通用的数据。这样可以对所有数据类型进行非常快速的“简单”搜索。
我创建了五个单独的SubType,分别为五个数据Feed中的每个存储了唯一的数据元素。每个SuperType记录与适当的SubType记录具有1:1的关系。
如果客户要进行详细搜索,则必须选择Super-Sub类型,例如PropertyResidential。
在我看来,1:1关系在RDBMS上映射了一个类Inheritance。有一个表A,其中包含公用属性,即,分区类状态每个继承的类状态都在表B上映射到RDBMS,表B与包含专用属性的表A的关系为1:1。表namend A还包含一个表示“广播”功能的“类型”字段
再见马里奥
如果数据库中有某种类型的对象,则可能会出现。
在表T1中说,您具有具有一对一关系的列C1,C2,C3…。可以,它采用标准化形式。现在说在表T2中,您还有具有一对一关系的列C1,C2,C3,……(名称可能不同,但类型和作用相同)。出于与T1相同的原因,T2可以。
但是,在这种情况下,我看到适合一个单独的表T3,其中包含C1,C2,C3…,以及从T1到T3和从T2到T3的一对一关系。如果存在另一个表,并且已经存在一个一对多的C1,C2,C3…从表A到表B中的多行,我什至会更合适。然后,使用B代替T3,并使用从T1到B的一对一关系,从T2到B的关系相同,而从A到B的关系仍然相同。
我认为规范化与此不同,这可能是一个超出概念的想法:使用某些表中的一对一关系以及一对多的关系,识别对象类型并将相同类型的对象移动到其自己的存储池中其他表的关系。
出于安全目的,这不是必需的,但是有更好的方法来执行安全检查。想象一下,您创建了一个只能打开一扇门的钥匙。如果钥匙可以打开其他任何门,则应响警报。本质上,您可以具有“ 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号公民是骗伯尔尼的骗子。只是一个例子。
在两个地方,两个完全独立的实体共享一对一的关系。必须有很多示例:
人<->牙医(1:N,所以错了!)
人<->医生(其1:N,所以也是错误的!)
人<->配偶(其1:0 | 1,因此大多是错误的!)
编辑:是的,这些都是非常糟糕的例子,特别是如果我一直在寻找1:1,而不是两边都是0或1的情况。我想我的大脑开火了:-)
所以,我会再试一次。经过一番思考,事实证明,拥有两个必须(就软件而言)必须始终在一起的单独实体的唯一方法是,它们必须以更高的分类存在在一起。然后,当且仅当您陷入较低的分解阶段时,事物才是并且应该分开的,但是在更高的层次上,它们不能没有彼此而生存。上下文是关键。
对于医学数据库,您可能需要存储有关身体特定区域的不同信息,并将它们保留为单独的实体。在这种情况下,患者只有一个头,他们需要头,或者他们不是患者。(它们也有一颗心脏,以及许多其他必要的单个器官)。例如,如果您对跟踪手术感兴趣,那么每个区域应该是一个唯一的独立实体。
在生产/库存系统中,如果您要跟踪车辆的装配,那么您当然希望观察发动机与车身的进度不同,但是存在一对一的关系。一个护理必须有一个引擎,并且只有一个引擎(否则它将不再是“汽车”)。引擎仅属于一辆汽车。
在每种情况下,您都可以将单独的实体作为一个大记录来生成,但是考虑到分解级别,那将是错误的。在这些特定情况下,它们是真正的独立实体,尽管在更高层次上可能不会出现。
保罗