INSERT INTO ... FROM SELECT ... RETURNING id mappings

时间:2015-03-25 13:21:42

标签: sql postgresql sql-insert sql-returning

我正在使用PostgreSQL 9.3。

我想复制一些db记录。由于我使用了表的自动增量pk id,我想从生成的重复记录ID返回到原始ID的id映射。例如,假设我有一个表posts,其中包含2条记录:

 [{'id': 1, 'title': 'first'}
, {'id': 2. 'title': 'second'}]

使用SQL:

INSERT INTO posts (title) SELECT title FROM posts RETURNING id, ??

我希望看到像这样的映射:

 [{'id': 3, 'from_id': 1}
, {'id': 4, 'from_id': 2}]

有关如何填写上述问号以使其有效的任何想法?非常感谢!

3 个答案:

答案 0 :(得分:8)

这对于UPDATE来说会更简单,RETURNING子句可以看到加入更新的其他行:

INSERT目前可能 Per documentation:

  

表达式可以使用由 table_name

命名的表的任何列名

table_name INSERT命令的目标。

您可以使用(data-modifying) CTEs来实现此功能 假设title每个查询唯一,否则您需要执行更多操作:

WITH sel AS (
   SELECT id, title
   FROM   posts
   WHERE  id IN (1,2)   -- select rows to copy
   )
,    ins AS (
   INSERT INTO posts (title)
   SELECT title FROM sel
   RETURNING id, title
 )
SELECT ins.id, sel.id AS from_id
FROM   ins
JOIN   sel USING (title);

如果title每个查询不唯一(但每个表至少id是唯一的):

WITH sel AS (
   SELECT id, title, row_number() OVER (ORDER BY id) AS rn
   FROM   posts
   WHERE  id IN (1,2)   -- select rows to copy
   ORDER  BY id
   )
,    ins AS (
   INSERT INTO posts (title)
   SELECT title FROM sel ORDER  BY id  -- ORDER redundant to be sure
   RETURNING id
 )
SELECT i.id, s.id AS from_id
FROM  (SELECT id, row_number() OVER (ORDER BY id) AS rn FROM ins) i
JOIN   sel s USING (rn);

第二个查询依赖于未提供的实现细节,即按所提供的顺序插入行。它适用于所有当前版本的Postgres,可能不会破坏。

SQL Fiddle.

答案 1 :(得分:2)

id生成的posts nextval('posts_id_seq'::regclass)with sel as ( SELECT id, title, nextval('posts_id_seq'::regclass) new_id FROM posts WHERE id IN (1,2) ), ins as ( INSERT INTO posts (id, title) SELECT new_id, title FROM sel ) SELECT id, new_id FROM sel 您可以为每个新行手动调用此函数

title

它适用于任何数据,包括非唯一heightForRowAtIndexPath

答案 2 :(得分:0)

最简单的解决方案是IMHO只需在表中添加一列,您可以在其中放置已克隆行的ID。

相关问题