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

发布于 2024-08-10 17:06:27 字数 370 浏览 8 评论 0原文

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

这个想法是有两种类型的实体,A 和B. 它们可以单独存在,但它们之间也可以有联系。如果存在链接,那么它一定是 1:1 链接,并且是双向的。

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

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

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

Yesterday while working on a project I came up on a peculiar 1:1 relationship which left me wondering - how to best implement this (clearly, we had done it wrong :D)

The idea is that there are two types of entities, A and B. They can each exist on their own just fine, but they can also have a link between them. If there is a link, then it must be a 1:1 link, and work both ways.

It's like a bottle and a cap. They can exist apart, but when coupled together the bottle will have just one cap, and the cap will be attached to just one (and the same) bottle.

How would you implement this relationship while keeping in mind all the best practices about normalization, data integrity, etc?

Added: Almost forgot to say - they each have more than a dozen properties, so putting them in the same table with half of the fields being NULL is a pretty awkward solution. Also, the link can be broken and recreated with another entity at any time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

爱你是孤单的心事 2024-08-17 17:06:27

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

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

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

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

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

To solve this, I would start with the standard many-to-many relationship layout.

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

I would then use triggers, unique indexes, constraints to enforce the 1:1 relationship in the table. The exact method would depend on the system needs.

The reason I like this format is that many relationships have attributes as part of the relationship which are not part of the entities. This pattern allows for that now and in the future.

For example: a person works for a company. The relationship has a hire date which does not fit with the person entity or the company entity.

如痴如狂 2024-08-17 17:06:27
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
                )
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
                )
埋情葬爱 2024-08-17 17:06:27

我认为架构应该是这样的:

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。

I think the schema would look like this:

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 can only reference one row in A, and since the field is unique, A can only be referenced by one row in B.

B.A_id is nullable, so rows can exist in A and B that don't reference each other.

The unique constraint doesn't preclude multiple NULL records existing. A unique constraint ensures that the values are all either unique, or NULL.

执笔绘流年 2024-08-17 17:06:27

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

Nullable foreign key with a unique constraint at one or both ends depending (at boths ends is interesting!)

浮世清欢 2024-08-17 17:06:27

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

Separate join table of foreign key referencing A against foreign key referencing B, both columns with UNIQUE constraint. So either a link between two entities exists and is the only link for either of them, or no link exists so there's no row in the table.

蓝海 2024-08-17 17:06:27

我将使用 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 中tableB 条目未链接到 tableA。

该约束将强制执行从 tableA 到 tableB 或 tableB 到 tableA 的最多一个链接

I would use the solution proposed by Darryl:

TableA
  AId
  AInfo

TableB
  BId
  BInfo

TableA2B
  AId
  BId

and then just add unique constrain on AId in tableA2B and BId on tableA2B

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

I think that would solve your problem

The tableA entries that are not linked to any tableB entries would simply not be present in the TableA2B similarly tableB entries not linked to tableA.

The constrains would enforce maximum one link from tableA to tableB or tableB to tableA

枕头说它不想醒 2024-08-17 17:06:27

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

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

There are IMO two different cases to consider. Case one is best pictured with a monogamous marriage: the two objects are created independendly, and at some point in time, they are joined; later, they might be detached, and possible joined with other objects. For such a relationship, I'd propose the A2B table approach used by many others here.

Case two is pictured with twins: if the two objects are connected, they are so since birth and they are so till one of them dies. For that case, you could choose to simply give both of them the same primary key during creation (e.g. in Oracle by selecting one value from a sequence and using it as ID for both tables).

萝莉病 2024-08-17 17:06:27

“两端都有外键。当你尝试建立/断开链接时也很尴尬。必须求助于触发器和其他东西。我希望有一种更优雅的武器。”

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

达里尔彼得森的回应表明了这个解决方案在逻辑上是正确的。但是,由于 SQL 缺乏对“多重赋值”的 TTM 概念的支持,某些“更改链接”的情况可能会成为 SQL 中的噩梦。

"A foreign key at both ends. It's also awkward when you try to establish/break a link. Has to resort to triggers 'n stuff. I was hoping for a more elegant weapon."

You will not find such an elegant weapon in the universe of SQL-based systems.

Darryl Peterson's response shows the solution that is logically correct. But some cases of "changing a link" can become a nightmare in SQL due to its lack of support for the TTM concept of "multiple assignment".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文