PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

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

Ce serait plus simple pour UPDATE , où les lignes supplémentaires jointes dans la mise à jour sont visibles pour le RETURNING clause :

  • Renvoyer les valeurs de colonne pré-UPDATE en utilisant SQL uniquement - Version PostgreSQL

La même chose n'est actuellement pas possible pour INSERT . Par documentation :

L'expression peut utiliser n'importe quel nom de colonne de la table nommée par table_name

table_name étant la cible du INSERT commande.

Vous pouvez utiliser des CTE (modifiant les données) pour que cela fonctionne.
En supposant title être unique par requête , sinon vous devez en faire plus :

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);

Si title n'est pas unique par requête (mais au moins id est unique par table) :

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);

Cette deuxième requête s'appuie sur le détail d'implémentation non documenté selon lequel les lignes sont insérées dans l'ordre fourni. Il fonctionne dans toutes les versions actuelles de Postgres et ne va probablement pas tomber en panne.

SQL Fiddle.