2

昨天在做一个项目时,我遇到了一种特殊的 1:1 关系,这让我想知道——如何最好地实现这一点(显然,我们做错了 :D)

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

这就像一个瓶子和一个帽子。它们可以分开存在,但是当结合在一起时,瓶子将只有一个盖子,而盖子将仅连接到一个(并且是同一个)瓶子上。

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

补充:差点忘了说——它们每个都有十几个属性,所以将它们放在同一个表中,其中一半字段为 NULL 是一个非常尴尬的解决方案。此外,可以随时断开链接并与另一个实体重新创建链接。

4

9 回答 9

7

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

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

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

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

例如:一个人在一家公司工作。该关系的聘用日期不适合个人实体或公司实体。

于 2009-11-13T13:07:15.907 回答
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
                )
于 2009-11-13T16:34:34.757 回答
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。

于 2009-11-13T13:07:53.907 回答
0

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

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

于 2009-11-13T16:53:22.720 回答
0

将引用 A 的外键与引用 B 的外键分开连接表,两列都具有 UNIQUE 约束。因此,要么存在两个实体之间的链接并且是它们中的任何一个的唯一链接,要么不存在链接,因此表中没有行。

于 2009-11-13T13:27:03.433 回答
0

“两端都有外键。尝试建立/断开链接时也很尴尬。不得不求助于触发器。我希望有一个更优雅的武器。”

在基于 SQL 的系统的世界中,您将找不到如此优雅的武器。

Darryl Peterson 的回答显示了逻辑上正确的解决方案。但是某些“更改链接”的情况可能会成为 SQL 中的噩梦,因为它缺乏对“多重赋值”的 TTM 概念的支持。

于 2009-11-13T23:33:24.793 回答
0

Tony Rogerson 有一篇很棒的博客文章: How to Create a One-to-One Relationship in SQL Server using DRI, Triggers and Views

于 2011-03-18T19:06:56.783 回答
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 的最多一个链接

于 2009-11-13T16:24:15.890 回答
0

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

于 2009-11-13T13:02:23.237 回答