如何在RDBMS中最好地实现1:1关系?

时间:2009-11-13 12:44:52

标签: database-design rdbms rdbms-agnostic

昨天在从事一个项目时,我想出了一种特殊的1:1关系让我感到疑惑 - 如何最好地实现这一点(显然,我们做错了:D)

这个想法是有两种类型的实体,A和B.它们可以各自独立存在,但它们之间也可以有链接。如果有链接,则它必须是1:1链接,并且双向工作。

就像一个瓶子和一个帽子。它们可以分开存在,但当它们连在一起时,瓶子只有一个盖子,盖子只能连接到一个(和相同的)瓶子上。

您如何实现这种关系,同时牢记有关规范化,数据完整性等的所有最佳实践?

添加:几乎忘了说 - 他们每个都有十几个属性,所以将它们放在同一个表中,其中一半字段为NULL是一个非常尴尬的解决方案。此外,可以随时破坏链接并使用其他实体重新创建链接。

9 个答案:

答案 0 :(得分:7)

要解决这个问题,我会从标准的多对多关系布局开始。

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

然后我会使用触发器,唯一索引,约束来强制执行表中的1:1关系。确切的方法取决于系统需求。

我喜欢这种格式的原因是许多关系将属性作为关系的一部分而不是实体的一部分。这种模式允许现在和将来。

例如:一个人为公司工作。该关系的雇用日期与个人实体或公司实体不相符。

答案 1 :(得分:2)

我认为架构看起来像这样:

create table A (
    A_id    integer    primary key,
    ...
);

create table B (
    B_id    integer    primary key,
    A_id    integer    references A (A_id),
    ...
);

alter table B add constraint c1 unique(A_id);

B只能引用A中的一行,并且因为该字段是唯一的,所以A只能被B中的一行引用。

B.A_id可以为空,因此A和B中的行不能相互引用。

唯一约束不排除存在多个NULL记录。唯一约束可确保值都是唯一的,或者为NULL。

答案 2 :(得分:2)

CREATE TABLE A (id INT NOT NULL PRIMARY KEY, field1, …)

CREATE TABLE B (id INT NOT NULL PRIMARY KEY, field1, …)

CREATE TABLE AB (aid INT NOT NULL, bid INT NOT NULL,
                CONSTRAINT pk_ab PRIMARY KEY (aid, bid),
                CONSTRAINT ux_a UNIQUE (aid), 
                CONSTRAINT ux_b UNIQUE (bid),
                CONSTRAINT fk_aid_a FOREIGN KEY (aid) REFERENCES A,
                CONSTRAINT fk_bid_b FOREIGN KEY (bid) REFERENCES B
                )

答案 3 :(得分:0)

可以在一端或两端具有唯一约束的可空外键(两端都很有趣!)

答案 4 :(得分:0)

引用外键A的外键连接表与外键引用B,两列都具有UNIQUE约束。因此,两个实体之间存在链接,并且是其中任何一个实体的唯一链接,或者没有链接存在,因此表中没有行。

答案 5 :(得分:0)

我会使用Darryl提出的解决方案:

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

然后只需在tableA2B上的AId和tableA2B上的BId中添加唯一约束

alter TableA2B add constraint ucAId unique(AId)
alter TableA2B add constraint ucBId unique(BId)

我认为这可以解决您的问题

未链接到任何tableB条目的tableA条目将不会出现在TableA2B中,类似于未链接到tableA的tableB条目。

约束将强制执行从tableA到tableB或tableB到tableA

的最大链接

答案 6 :(得分:0)

IMO有两种不同的案例需要考虑。案例一最好用一夫一妻制婚姻描绘:两个对象是独立创造的,并且在某个时间点,它们是连在一起的;之后,它们可能会被分离,并且可能与其他对象结合在一起。对于这种关系,我建议在这里使用其他许多人的A2B表方法。

案例二与双胞胎合照:如果两个物体相连,那么从出生开始它们就是这样,直到其中一个死亡。对于这种情况,您可以选择在创建期间简单地为它们提供相同的主键(例如,在Oracle中,通过从序列中选择一个值并将其用作两个表的ID)。

答案 7 :(得分:0)

“两端的外键。当你试图建立/破坏一个链接时也很尴尬。必须诉诸触发器。我希望有一个更优雅的武器。”

在基于SQL的系统中,你不会找到这样优雅的武器。

Darryl Peterson的回答显示了逻辑上正确的解决方案。但是由于缺乏对“多重分配”的TTM概念的支持,一些“改变链接”的案例可能成为SQL的噩梦。

答案 8 :(得分:0)