我正在研究一个涉及四个表的数据库模式:
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 构造或设计模式?
感谢您的帮助。
虽然
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 |