【问题标题】:Can there be a 1 to 1 relationship for keys with multiple fields?具有多个字段的键可以存在 1 对 1 的关系吗?
【发布时间】:2020-05-04 11:13:27
【问题描述】:

我正在创建用于数据库管理的网络应用程序。可以使用图表 ER 创建数据库。
这是我的应用程序的屏幕:

如您所见,这个伪示例显示了 4 种类型的案例:
1) 主键 --> 主键 (1:1)
2) 唯一键 --> 唯一键 (1:1)
3) 由两个字段组成的主键 --> 由两个字段组成的主键 (1:1)
4) 由两个字段组成的唯一键 --> 由两个字段组成的唯一键 (1:1)

这是我的问题:
这一切都是真的吗?我想知道这些双键...这真的是一对一的关系吗?
一般来说,我也想知道前两个案例。还有真的吗?

MySQL Workbench 显示不正确:

我不知道为什么,但您可以看到 MySQL Workbench 显示这是一对多关系...

Oracle Sql 开发者:

谁能告诉我真正的一对一关系是什么时候?
文档显示我有权利:
https://docs.oracle.com/cd/E26180_01/Platform.94/RepositoryGuide/html/s1204onetoonewithauxiliarytable01.html
但是 MySQL Workbench 和 Sql Developer 中的图表 ER 显示了一些不同的东西......

该表中的 SQL 代码:

CREATE USER "Student" IDENTIFIED BY "null";

CREATE TABLE "Student".Table1 (
    PK_FK NUMBER NOT NULL
);
CREATE TABLE "Student".Table2 (
    PK NUMBER NOT NULL
);
CREATE TABLE "Student".Table3 (
    PK NUMBER NOT NULL,
    UK_FK NUMBER
);
CREATE TABLE "Student".Table4 (
    PK NUMBER NOT NULL,
    UK NUMBER
);
CREATE TABLE "Student".Table5 (
    PK_1_FK NUMBER NOT NULL,
    PK_2_FK NUMBER NOT NULL
);
CREATE TABLE "Student".Table6 (
    PK_1 NUMBER NOT NULL,
    PK_2 NUMBER NOT NULL
);
CREATE TABLE "Student".Table7 (
    UK_1_FK NUMBER,
    UK_2_FK NUMBER
);
CREATE TABLE "Student".Table8 (
    UK_1 NUMBER,
    UK_2 NUMBER
);

ALTER TABLE "Student".Table1 ADD CONSTRAINT Table1_PK PRIMARY KEY (PK_FK);
ALTER TABLE "Student".Table2 ADD CONSTRAINT Table2_PK PRIMARY KEY (PK);
ALTER TABLE "Student".Table3 ADD CONSTRAINT Table3_PK PRIMARY KEY (PK);
ALTER TABLE "Student".Table4 ADD CONSTRAINT Table4_PK PRIMARY KEY (PK);
ALTER TABLE "Student".Table5 ADD CONSTRAINT Table5_PK PRIMARY KEY (PK_1_FK, PK_2_FK);
ALTER TABLE "Student".Table6 ADD CONSTRAINT Table6_PK PRIMARY KEY (PK_1, PK_2);
ALTER TABLE "Student".Table3 ADD CONSTRAINT Table3_UK1 UNIQUE (UK_FK);
ALTER TABLE "Student".Table4 ADD CONSTRAINT Table4_UK2 UNIQUE (UK);
ALTER TABLE "Student".Table7 ADD CONSTRAINT Table7_UK3 UNIQUE (UK_1_FK, UK_2_FK);
ALTER TABLE "Student".Table8 ADD CONSTRAINT Table8_UK4 UNIQUE (UK_1, UK_2);
ALTER TABLE "Student".Table1 ADD CONSTRAINT Table1_FK1 FOREIGN KEY (PK_FK)
REFERENCES "Student".Table2 (PK);
ALTER TABLE "Student".Table3 ADD CONSTRAINT Table3_FK2 FOREIGN KEY (UK_FK)
REFERENCES "Student".Table4 (UK);
ALTER TABLE "Student".Table5 ADD CONSTRAINT Table5_FK3 FOREIGN KEY (PK_1_FK, PK_2_FK)
REFERENCES "Student".Table6 (PK_1, PK_2);
ALTER TABLE "Student".Table7 ADD CONSTRAINT Table7_FK4 FOREIGN KEY (UK_1_FK, UK_2_FK)
REFERENCES "Student".Table8 (UK_1, UK_2);

【问题讨论】:

  • 我问的是 1 对 1 的关系是否真的发生在我发布的 4x 案例中。我需要实现它。
  • 您的第一张图片描绘了四个一对一的关系。要确定,您应该从生成的 ddl 发布主键和外键文本。那我们就肯定知道了。您可以发布 all 的 ddl 命令,但您只需发布关键信息。此外,如果您不确定,则可以通过尝试插入会违反您要强制执行的规则的行来测试关系的执行情况。
  • 是的,当然。
  • Jeff Holt,我编辑了帖子,你现在可以看到 sql 代码了。

标签: mysql sql oracle postgresql


【解决方案1】:

这完全有可能。以下是 PostgreSQL 的示例:

create table t1 (
  a int not null,
  b int not null,
  constraint uq1 (a, b),
  constraint fk1 foreign key (a, b) references t2 (a, b)
    deferrable initially deferred
);

create table t2 (
  a int not null,
  b int not null,
  constraint uq2 (a, b),
  constraint fk2 foreign key (a, b) references t1 (a, b)
    deferrable initially deferred
);

在这种情况下 t1 (a,b) 是唯一的,并且引用 t2 (a, b) 也是唯一的。这是使用“复合键”的 1:1 关系。

注意:本示例使用“循环引用”,它是 SQL 的标准部分,但 [据我所知] 仅由 PostgreSQL 和 Oracle 实现。它不会在 MySQL 中运行。

【讨论】:

  • 现在编写向 T1 和 T2 插入记录的 SQL :)
  • @APC 当然可以,但是插入只能在 PostgreSQL 和 Oracle 中运行。您需要将约束检查推迟到“事务”级别,而不是语句或行级别。可延迟性是 SQL 标准的一个组成部分,但仅在这两个数据库中实现。在stackoverflow.com/questions/5300307/…查看我的回答
  • 我一直认为需要延迟约束是数据模型损坏的标志。见my answer to an "interview question" question here
  • @APC 我听到了。此功能几乎没有用处,大多数时候您可能希望将 1:1 关系保留为单个表。
【解决方案2】:

一对一的关系仍然是主从关系。一个表是标识符的所有者,另一个表通过外键引用它。这是 MySQL Workbench 和 SQL Developer 图片中显示的关系。

文档显示我有权利:

您链接到 ATG 存储库的 Oracle 文档,它是一种用于通用表示数据的专业工具,但即使在那里,我们也可以从 SQL 中看到 USER_TBL 是主表并“拥有” ID 列,而 JOB_TBL 是辅助表并引用 ID。

CREATE TABLE usr_tbl (
        id                      VARCHAR(32)     not null,
        nam_col                 VARCHAR(32)     null,
        age_col                 INTEGER null,
        primary key(id)
);

CREATE TABLE job_tbl (
        id                      VARCHAR(32)     not null references usr_tbl(id),
        function                VARCHAR(32)     null,
        title                   VARCHAR(32)     null,
        primary key(id)

换句话说,我们可以有一个没有 JOB 的 USER,但我们不能有一个没有 USER 的 JOB。但是一个 USER 只能有一个 JOB,而一个 JOB 只属于一个用户。

您的图表是错误的,因为它将 TABLE7 和 TABLE8 呈现为对等点。但是外键不是那样工作的。一张桌子服从另一张桌子。当我查看您的符号时,我看不出是 TABLE8 拥有 TABLE7 还是 TABLE7 拥有 TABLE8。然而,在 MySQL 和 Oracle 图表中非常清楚。数据模型的目的是阐明数据库设计而不是混淆它。


注意,定义两个具有引用彼此主键的外键的表是完全可能的。诀窍是将数据插入其中。这需要推迟外键约束。我认为延迟约束是一个危险信号,是数据模型损坏的标志。

【讨论】:

  • 嗯,我不清楚为什么你认为我的表 7 和 8 被呈现为对等。如果我要从 usr_tbl 中删除“nam_col”和“age_col”,我也会从 job_tbl 中删除“function”和“title”。这些表看起来不一样吗?除了双键之外唯一的区别是我使用了alter table
  • 嗯,我看了你的符号,我看不出是 TABLE8 拥有 TABLE7 还是 TABLE7 拥有 TABLE8。在 MySQL 和 Oracle 图表中非常清楚。数据模型的目的是澄清数据库设计而不是混淆它。
  • 啊...我终于明白你的意思了。你认为我的图表简直难以辨认?事实上,这正是我真正想知道的。我应该如何标记它?如您所见,oracle 使用箭头清楚地显示了谁是关系的发起者。我应该这样做吗?
  • 现有几个data model notations。选择一个并始终如一地应用它。
猜你喜欢
  • 1970-01-01
  • 2022-12-22
  • 1970-01-01
  • 2015-10-10
  • 2013-12-20
  • 2019-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多