Sql 插入到。。。从选择。。。返回id映射

Sql 插入到。。。从选择。。。返回id映射,sql,postgresql,sql-insert,sql-returning,Sql,Postgresql,Sql Insert,Sql Returning,我正在使用PostgreSQL 9.3 我想复制一些数据库记录。因为我对表使用了一个自动递增的pk id,所以我想从生成的重复记录的id到原始记录的id映射。例如,假设我有一个表posts,其中包含2条记录: [{'id': 1, 'title': 'first'} , {'id': 2. 'title': 'second'}] 使用SQL: INSERT INTO posts (title) SELECT title FROM posts RETURNING id, ?? 我希望看到如下

我正在使用PostgreSQL 9.3

我想复制一些数据库记录。因为我对表使用了一个自动递增的pk 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}]
你知道如何填写上面的问号来让它工作吗?非常感谢

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

对于INSERT,目前无法执行相同的操作

表达式可以使用由table_name命名的表的任何列名

作为INSERT命令目标的表名称

你可以用它来工作。 假设每个查询的标题都是唯一的,否则您需要执行更多操作:

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);
如果每个查询的标题不是唯一的,但每个表的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,并且可能不会崩溃


IMHO最简单的解决方案是简单地向表中添加一列,在其中可以放置克隆行的id

由nextval'posts\u id\u seq'生成的帖子的if id列::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

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

我想你可以通过别名来实现:FROM posts oldposts,然后在RETURNING子句中引用新旧别名。不过看起来不像。“狡猾!”克雷格·格林格是的,我也试过了。想知道为什么它不能这样工作。它几乎是重复的,没有公认的答案。是的,这可能是最简单的,也可能适合其他SQL数据库。但是它给数据库模式增加了额外的复杂性。第二个查询中的最后第二行的列别名应位于SELECT id的partition子句之外,ORDER BY id上的行号应为rn FROM insi@ErwinBrandstetter你对这种方法有什么看法?