如何解决复制行和外键行,保持关系/顺序
我有两个具有 1:1 关系的表 (Postgresql 12):
CREATE TABLE public.objects (
id uuid DEFAULT public.gen_random_uuid () NOT NULL PRIMARY KEY UNIQUE,name text NOT NULL,object_type_a_id uuid NOT NULL
);
CREATE TABLE public.object_type_a (
id uuid DEFAULT public.gen_random_uuid () NOT NULL PRIMARY KEY UNIQUE,description text NOT NULL
);
ALTER TABLE ONLY public.objects
ADD CONSTRAINT objects_object_type_a_id_fkey FOREIGN KEY (object_type_a_id) REFERENCES public.object_type_a (id) ON UPDATE RESTRICT ON DELETE RESTRICT;
INSERT INTO public.object_type_a (description) VALUES ('desc_1'),('desc_2'),('desc_3');
INSERT INTO objects (name,object_type_a_id) SELECT 'name_1',id FROM object_type_a WHERE description = 'desc_1';
INSERT INTO objects (name,object_type_a_id) SELECT 'name_2',id FROM object_type_a WHERE description = 'desc_2';
INSERT INTO objects (name,object_type_a_id) SELECT 'name_3',id FROM object_type_a WHERE description = 'desc_3';
我现在必须复制 objects
和 object_type_a
中的所有行,保持关系以及 objects.name
和 object_type_a.description
中的所有值,所以它看起来像这样:
objects
---------------------------------
id | name | object_type_a_id
---------------------------------
847c..| name_1 | 5b7d..
ae3e..| name_2 | 4ce4..
41fd..| name_3 | bffa..
d570..| name_1 | eeec..
4cfd..| name_2 | 4bb0..
892f..| name_3 | aeff..
object_type_a
--------------------
id | description
--------------------
5b7d..| desc_1
4ce4..| desc_2
bffa..| desc_3
eeec..| desc_1
4bb0..| desc_2
aeff..| desc_3
我尝试使用 CTE/子查询,从 objects
和 object_type_a
中选择所有行,然后插入/更新 objects
,但这显然会混淆关系并执行此操作一次一行似乎效率很低。
解决方法
假设description
在“a”表中是唯一的,那么可以采用以下方法:
- 将新的“a”对象插入到“a”表中。
- 查找现有的“a”对象,然后根据
description
匹配新插入的对象。 - 将此匹配用于插入行。
Postgres 允许带有 DML 语句的 CTE,返回更改行的值,因此这一切都可以在一个语句中完成:
with oa as (
insert into objects_type_a (description)
select description
from object_type_a oa
where exists (select 1 from objects o where oa.id = o.object_type_a_id)
returning *
)
insert into objects (name,object_type_a_id)
select o.name,oa.id
from objects o join
object_type_a oa_orig
on o.object_type_a_id = oa_orig.id join
oa
on oa_orig.description = oa.description;
Here 是一个 dbfiddle。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。