数据库关系 1:1 vs 1:0..1

4
我正在尝试学习这些关系。如果我按照下面的方式表示,是否正确:
1)通过将父项的标识键也作为子项的标识键,我将拥有一个1:0..1的关系?
2)要使其成为1:1,我在父表中添加一个外键,连接两个标识列?
这就是全部内容吗?如果我的措辞不准确/正确,请纠正我。
1:0..1

客户(Id {主键, 自增长}, 姓名)

客户地址(CustomerId {主键, 外键, 自增长}, 街道名称)

外键_客户地址_客户(CustomerId, Id)

1:1

客户(Id {主键, 外键, 自增}, 名字)

FK_客户_客户地址(Id, 客户Id)

客户地址(客户Id {主键, 外键, 自增}, 街道名称)

FK_客户地址_客户(客户Id, Id)


编辑1:

我认为以上两个都是错误的,正确的解决方案应该是这样的: (?)

1:0..1

客户(Id{主键, 自增}, 姓名)

客户地址(客户Id{主键, 外键, 唯一}, 街道名称)

外键_客户地址_客户(客户Id, Id)


我不知道您是否指的是 1:0..1(“一到零或一”)。 - onedaywhen
是的,我是这个意思,会修改。 - bretddog
如果你的意思是客户而不是服装设计师(costumer),请修正你的表格和字段拼写。而且,ID作为标识字段是一个糟糕的选择。它会导致报告出现问题(报告不喜欢具有相同名称的多个列),并且在连接中很容易出错。请使用tablenameId代替。 - HLGEM
3个回答

8

两个表之间的一对一关系意味着每个表中的每个元组都映射到另一个表中的恰好一个元组。这更正式地称为双射。对于大多数实际目的而言,在SQL数据库中实现双射实际上是不可能的,这是SQL的限制。因为SQL要求每个表单独更新,所以除非您暂时禁用其中一个约束,否则没有办法同时更新两个表。

1:0/1关系也称为满射(您的第一个示例)。假设不允许空值,满射是类似SQL风格的“外键”约束的标准行为。这种约束在关系的一侧总是可选的。

注意:IDENTITY属性与您的示例无关。定义关系的是键和外键约束。


1
支持可延迟约束的数据库管理系统(DBMS),可以仅使用DDL强制执行1:1关系。如果必要的话,您可能可以通过触发器在SQL Server上获得相同的效果,但我现在太累了,无法考虑那么复杂的事情。 - Mike Sherrill 'Cat Recall'
是的,您可以使用可延迟约束来实现。但是,可延迟约束只是一种可以暂时禁用的约束,以便每次更新时都可以违反约束。换句话说,该约束根本不被视为声明性约束来执行。在这方面,SQL对多表约束的支持非常有限。在SQL Server中的解决方法是禁用约束,然后重新启用它。 - nvogel
1
@dportas: "可延迟的约束只是一种可以暂时禁用的约束,以便每次更新时都可以违反约束。" 这是一种看待它的方式。另一种方式是说可延迟的约束是在任意一系列SQL语句(在事务结束时)的末尾检查的约束,而不是在中间某个地方。 - Mike Sherrill 'Cat Recall'
哦..我当然得移除CustomerAddressID上的Identity,然后才能插入。请参见上面的EDIT1。那么这样就正确了吗? - bretddog
bretddog,IDENTITY 只是一种为每个插入的行生成新数字的功能。IDENTITY 列不必具有唯一值,而唯一的列不必是 IDENTITY。 - nvogel
显示剩余3条评论

4

外键只能单向指向一个表,如果你让它双向指向两个表,那么你就无法插入一行数据,因为插入操作只能在一个表上进行。

因此,通常情况下,你所列出的 1:0,1 的解决方案被用于这两种情况。据我所知,SQL Server 没有办法强制执行 1:1 约束中的第二个 1。


太好了!开始有点明白了 :) - bretddog
1
bretdog... 别忘了接受一个答案。否则你会招致坏名声,最终不再得到任何回答 :P - Brett Rossier
1
Oracle和PostgreSQL都支持“可延迟约束”这一标准特性。你可以有效地建立1:1关系。 - The Impaler

1

“规范化的优势”是什么意思?难道不应该一开始就不使用1:1吗? - bretddog
@bretddog:这不是我的话,而是Hugh Darwen的话。请点击链接(http://www.dbdebunk.com/page/page/3010532.htm)并阅读文章! :) - onedaywhen
好的,我仍然不理解。有点超出我的水平了。既然您使用引用,您应该能够解释一下.. ;) - bretddog
@bretddog:"你应该能够解释... ;)" -- 我会试试 :) 拥有循环 FK 的缺点是你将遭受规范化所防止的更新异常,例如删除一个地址将导致客户被删除,不能在不知道他们的地址的情况下将客户输入到数据库中等。就我个人而言,似乎“地址”是“客户”的属性,而不是两个实体之间的1:1关系。 - onedaywhen
我明白了。知道删除等操作的情况很好,我还没有尝试过...这些表只是举例而已。我有一个大约有100列的表,它们在逻辑上属于3个不同的类别。所以将其分成3个表并使其中两个与第一个表具有1:1的关系会更容易管理。我相信我也会将这些“类别”映射到1:1的父子域对象中,因此(?)这也可能使存储库更容易编写。 - bretddog

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