在 PostgreSQL 中创建双向关系 table
Creating a 2-way relationship in PostgreSQL table
我有 3 个 table 代表房子、房间和抽屉的 UUID、名称、位置和信息(这是一个示例,因为我的工作很敏感)。
因此,例如 1 所房子将有多个房间(一对多),而多个房间将包含多个抽屉(多对多)。
这个想法是,将创建一个关联 table,其中 table 中行的每个 UUID 将与另一个 table 中相应的 UUID 相关联。
例如,如果我查询 ID1 代表的房子,它将 return 以下内容:
SELECT * FROM house where 'ID_1='1';
| ID_1|ID_2 |
| ----| -----|
| 1 | 201 |
| 1 | 254 |
| 1 | 268 |
到目前为止,我已经创建了关联 table 的临时版本,说明我需要它如何在真实 table 中表示。但是,现在我需要一个函数来自动为从临时关联 table 到真实关联 table 的所有行正确填写 ID。例如:
INSERT INTO associations (id_1, id_2) VALUES
('1','201'),
('201','1')
我需要它是无方向的,这样当我查询 id_1 我也会在结果 id_2 中得到它的链接
假设您要获得单向关系的查询如下所示:
SELECT room_uuid AS left_uuid, house_the_room_is_in_uuid AS right_uuid
FROM rooms
WHERE house_the_room_is_in_uuid IS NOT NULL
AND is_active
要获得反向关系,只需将列表按其他顺序排列即可;查询的其余部分不需要更改,无论它多么复杂:
SELECT house_the_room_is_in_uuid AS left_uuid, room_uuid AS right_uuid
FROM rooms
WHERE house_the_room_is_in_uuid IS NOT NULL
AND is_active
这两个都将作为插入到具有两个 UUID 列的 table 中的查询有效:
CREATE TABLE my_lookup_table (left_uuid UUID, right_uuid UUID);
INSERT INTO my_lookup_table (left_uuid, right_uuid)
SELECT ... -- either of the above
要合并它们,请依次将每个插入相同的 table,或者使用 UNION
创建一个包含两组行的结果集:
SELECT room_uuid AS left_uuid, house_the_room_is_in_uuid AS right_uuid
FROM rooms
WHERE is_in_house_uuid IS NOT NULL
AND is_active
UNION
SELECT house_the_room_is_in_uuid AS left_uuid, room_uuid AS right_uuid
FROM rooms
WHERE is_in_house_uuid IS NOT NULL
AND is_active
联合所需的全部是查询具有相同数量和类型的列。名称(如果相关的话)来自第一个查询,但我发现如果您在两者中都包含别名,则它更具可读性。
因为 UNION
的结果本身只是一个两列的结果集,所以它可以像以前一样与相同的 INSERT
语句一起使用。这将允许您插入到 table 中,即使它有 a self-referencing foreign key constraint as discussed here:
ALTER TABLE my_lookup_table ADD CONSTRAINT
my_lookup_table_combinations_must_be_unique
UNIQUE (left_uuid, right_uuid);
ALTER TABLE my_lookup_table ADD CONSTRAINT
my_lookup_table_must_have_rows_both_ways_around
FOREIGN KEY (right_uuid, left_uuid)
REFERENCES my_lookup_table (left_uuid, right_uuid);
如果您尝试仅插入一组行,这会失败,但是对于 UNION
,在 statement/transaction 的末尾,每一行都在 table双向,所以约束得到满足。
我有 3 个 table 代表房子、房间和抽屉的 UUID、名称、位置和信息(这是一个示例,因为我的工作很敏感)。
因此,例如 1 所房子将有多个房间(一对多),而多个房间将包含多个抽屉(多对多)。
这个想法是,将创建一个关联 table,其中 table 中行的每个 UUID 将与另一个 table 中相应的 UUID 相关联。 例如,如果我查询 ID1 代表的房子,它将 return 以下内容:
SELECT * FROM house where 'ID_1='1';
| ID_1|ID_2 |
| ----| -----|
| 1 | 201 |
| 1 | 254 |
| 1 | 268 |
到目前为止,我已经创建了关联 table 的临时版本,说明我需要它如何在真实 table 中表示。但是,现在我需要一个函数来自动为从临时关联 table 到真实关联 table 的所有行正确填写 ID。例如:
INSERT INTO associations (id_1, id_2) VALUES
('1','201'),
('201','1')
我需要它是无方向的,这样当我查询 id_1 我也会在结果 id_2 中得到它的链接
假设您要获得单向关系的查询如下所示:
SELECT room_uuid AS left_uuid, house_the_room_is_in_uuid AS right_uuid
FROM rooms
WHERE house_the_room_is_in_uuid IS NOT NULL
AND is_active
要获得反向关系,只需将列表按其他顺序排列即可;查询的其余部分不需要更改,无论它多么复杂:
SELECT house_the_room_is_in_uuid AS left_uuid, room_uuid AS right_uuid
FROM rooms
WHERE house_the_room_is_in_uuid IS NOT NULL
AND is_active
这两个都将作为插入到具有两个 UUID 列的 table 中的查询有效:
CREATE TABLE my_lookup_table (left_uuid UUID, right_uuid UUID);
INSERT INTO my_lookup_table (left_uuid, right_uuid)
SELECT ... -- either of the above
要合并它们,请依次将每个插入相同的 table,或者使用 UNION
创建一个包含两组行的结果集:
SELECT room_uuid AS left_uuid, house_the_room_is_in_uuid AS right_uuid
FROM rooms
WHERE is_in_house_uuid IS NOT NULL
AND is_active
UNION
SELECT house_the_room_is_in_uuid AS left_uuid, room_uuid AS right_uuid
FROM rooms
WHERE is_in_house_uuid IS NOT NULL
AND is_active
联合所需的全部是查询具有相同数量和类型的列。名称(如果相关的话)来自第一个查询,但我发现如果您在两者中都包含别名,则它更具可读性。
因为 UNION
的结果本身只是一个两列的结果集,所以它可以像以前一样与相同的 INSERT
语句一起使用。这将允许您插入到 table 中,即使它有 a self-referencing foreign key constraint as discussed here:
ALTER TABLE my_lookup_table ADD CONSTRAINT
my_lookup_table_combinations_must_be_unique
UNIQUE (left_uuid, right_uuid);
ALTER TABLE my_lookup_table ADD CONSTRAINT
my_lookup_table_must_have_rows_both_ways_around
FOREIGN KEY (right_uuid, left_uuid)
REFERENCES my_lookup_table (left_uuid, right_uuid);
如果您尝试仅插入一组行,这会失败,但是对于 UNION
,在 statement/transaction 的末尾,每一行都在 table双向,所以约束得到满足。