如何对涉及弱实体及其父实体相关实体的复杂关系进行建模?

问题描述 投票:0回答:1

我正在研究一个涉及四个表的数据库模式:

A
B
C
D
。这些表之间的关系如下:

  • A
    可以包含表
    B
    中的一条或多条记录。
  • C
    可以包含表
    D
    中的一条或多条记录。
  • A
    C
    之间存在多对多关系,形成弱实体(联合表)“
    AC
    ”。
CREATE TABLE A (
    id INT PRIMARY KEY
);

CREATE TABLE B (
    id INT PRIMARY KEY,
    a_id INT,
    FOREIGN KEY (a_id) REFERENCES A(id)
);

CREATE TABLE C (
    id INT PRIMARY KEY
);

CREATE TABLE D (
    id INT PRIMARY KEY,
    c_id INT,
    FOREIGN KEY (c_id) REFERENCES C(id)
);

CREATE TABLE AC (
    a_id INT,
    c_id INT,
    PRIMARY KEY (a_id, c_id),
    FOREIGN KEY (a_id) REFERENCES A(id),
    FOREIGN KEY (c_id) REFERENCES C(id)
);

我的要求: 对于每个

AC
记录,我需要将与其 B
 关联的 
A
链接到与其 D
 关联的 
C

说明: 这看起来像是涉及

AC
B
D
的三元关系:在
AC
记录的上下文中,
B
需要链接到
D
。但是我们有额外的约束,即
B
需要属于
A
记录的
AC
,并且
D
需要属于同一
C
记录的
AC

我尝试过的:我尝试创建一个引用 AC、B 和 D 的简单“分配”表。但是,我无法强制执行上述约束。

CREATE TABLE assignment (
    id INT PRIMARY KEY,
    ac_a_id INT,  -- Foreign key referencing 'a_id' in AC
    ac_c_id INT,  -- Foreign key referencing 'c_id' in AC
    b_id INT,     -- Foreign key referencing 'id' in B
    d_id INT,     -- Foreign key referencing 'id' in D

    FOREIGN KEY (ac_a_id, ac_c_id) REFERENCES AC(a_id, c_id),
    FOREIGN KEY (b_id) REFERENCES B(id),
    FOREIGN KEY (d_id) REFERENCES D(id)
);

建模这种关系的好方法是什么?是否有最适合此场景的特定 SQL 构造或设计模式?

感谢您的帮助。

sql postgresql database-design erd
1个回答
0
投票

虽然

AC
是弱实体,但更恰当的说法是称为关联表(也称为桥接表)。不需要引用
AC
B
D
的“分配”表,您已经对
B
D
之间的关系进行了建模。为了进行演示,请运行以下命令来创建和填充表:

CREATE TABLE a (
  id integer PRIMARY KEY
);

CREATE TABLE b (
  id integer PRIMARY KEY,
  a_id integer REFERENCES a(id)
);

CREATE TABLE c (
  id integer PRIMARY KEY
);

CREATE TABLE d (
  id integer PRIMARY KEY,
  c_id integer REFERENCES c(id)
);

CREATE TABLE ac (
  a_id integer REFERENCES a(id),
  c_id integer REFERENCES c(id),
  CONSTRAINT ac_pk PRIMARY KEY (a_id, c_id)
);

INSERT INTO a(id)
SELECT generate_series(100, 109);

INSERT INTO b(id, a_id)
VALUES (200, 100),
       (201, 101),
       (202, 101),
       (203, 103);

INSERT INTO c(id)
SELECT generate_series(300, 309);

INSERT INTO d(id, c_id)
VALUES (400, 300),
       (401, 301),
       (402, 302),
       (403, 302);

INSERT INTO ac(a_id, c_id)
VALUES (100, 300),
       (101, 301),
       (102, 301),
       (103, 302),
       (104, 302),
       (104, 303);

以下查询返回从

B
D
AC
的关联行:

SELECT ac.a_id, b.id AS b_id, ac.c_id, d.id AS d_id
  FROM ac
  JOIN b ON ac.a_id = b.a_id
  JOIN d ON ac.c_id = d.c_id
  ORDER BY ac.a_id, b.id, ac.c_id, d.id;

上述查询的输出是:

a_id b_id c_id d_id
100 200 300 400
101 201 301 401
101 202 301 401
103 203 302 402
103 203 302 403
© www.soinside.com 2019 - 2024. All rights reserved.