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.