我正在尝试编写一个查询,将表中的行复制到同一个表中,为其提供一个新的顺序主键,并将其与新的外键相关联。我需要将新主键与未插入的另一个外键相关联,并存在于不同的关系表(查找表)中。
我希望能够将此作为单个事务执行,但我似乎无法找到将原始行与复制行关联的方法,因为复制行的唯一ID是新的。这将是一个有点口,但这是我的具体问题:
外部SELECT子句是否可以用内部SELECT子句和RETURNING包含内部INSERT,以便选择内部SELECT和INSERT的RETURNING子句中的值并正确连接?这是我尝试过的内容:
WITH batch_select AS (
SELECT id, owner_id, 1992 AS project_id
FROM batch
WHERE project_id = 1921
),
batch_insert AS (
INSERT INTO batch (owner_id, project_id)
SELECT bs.owner_id, bs.experiment_id
FROM batch_select bs
RETURNING id
)
SELECT bs.id AS origin_id, bi.id AS destination_id
FROM batch_select bs, batch_insert bi;
我需要origin_id对应于destination_id。显然现在它只是一个CROSS JOIN,其中所有东西都与所有东西配对并且不是很有用。我还将使用最后一个SELECT语句的结果将INSERT运行到查找表中,类似于这样(batch_join_select查询可以在最后一个插入中实现,但为了清楚起见):
WITH batch_select AS (
SELECT id, owner_id, 1992 AS project_id
FROM batch
WHERE project_id = 1921
),
batch_insert AS (
INSERT INTO batch (owner_id, project_id)
SELECT bs.owner_id, bs.experiment_id
FROM batch_select bs
RETURNING id
),
batch_join_select AS (
SELECT bs.id AS origin_id, bi.id AS destination_id
FROM batch_select bs, batch_insert bi
)
INSERT INTO lookup_batch_container (batch_id, container_id)
SELECT bjs.destination_id, lbc.container_id
FROM batch_join_select bjs
INNER JOIN lookup_batch_container lbc ON lbc.batch_id = bjs.origin_id;
我在dba交换机上发现了类似的question,但是当有多行时,接受的答案没有正确地将两者联系起来。
我是否只需要进行多次交易?
[编辑] 添加一些最小架构:
Table lookup_batch_container
Column | Type | Modifiers
--------------+---------+-----------
batch_id | integer | not null
container_id | integer | not null
Indexes:
"lookup_batch_container_batch_id_container_id_key" UNIQUE CONSTRAINT, btree (batch_id, container_id)
Foreign-key constraints:
"lookup_batch_container_batch_id_fkey" FOREIGN KEY (batch_id) REFERENCES batch(id) ON DELETE CASCADE
"lookup_batch_container_container_id_fkey" FOREIGN KEY (container_id) REFERENCES container(id) ON DELETE CASCADE
Table batch
Column | Type | Modifiers
------------------+-----------------------------+------------------------------------------------------------------------------------
id | integer | not null default nextval('batch_id_seq'::regclass)
owner_id | integer | not null
project_id | integer | not null
Indexes:
"batch_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"batch_project_id_fkey" FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE
"batch_owner_id_fkey" FOREIGN KEY (owner_id) REFERENCES owner(id) ON DELETE CASCADE
Referenced by:
TABLE "lookup_batch_container" CONSTRAINT "lookup_batch_container_batch_id_fkey" FOREIGN KEY (batch_id) REFERENCES batch(id) ON DELETE CASCADE
Table container
Column | Type | Modifiers
-----------------------+-----------------------------+------------------------------------------------------------------------------
id | integer | not null default nextval('stirplate_source_file_container_id_seq'::regclass)
owner_id | integer | not null
status | container_status_enum | not null default 'new'::container_status_enum
name | text | not null
Indexes:
"container_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"container_owner_id_fkey" FOREIGN KEY (owner_id) REFERENCES owner(id) ON DELETE CASCADE
Referenced by:
TABLE "lookup_batch_container" CONSTRAINT "lookup_batch_container_container_id_fkey" FOREIGN KEY (container_id) REFERENCES container(id) ON DELETE CASCADE
答案 0 :(得分:0)
with batch_select as (
select id, owner_id, 1992 as project_id
from batch
where project_id = 1921
), batch_insert as (
insert into batch (owner_id, project_id)
select owner_id, project_id
from batch_select
order by id
returning *
)
select unnest(oid) as oid, unnest(did) as did
from (
select
array_agg(distinct bs.id order by bs.id) as oid,
array_agg(distinct bi.id order by bi.id) as did
from
batch_select bs
inner join
batch_insert bi using (owner_id, project_id)
) s
;
oid | did
-----+-----
1 | 4
2 | 5
3 | 6
鉴于此batch
表:
create table batch (
id serial primary key,
owner_id integer,
project_id integer
);
insert into batch (owner_id, project_id) values
(1,1921),(1,1921),(2,1921);
如果主键是(id, owner_id, project_id)
,则可能更简单。不是吗?