Esto sería más simple para UPDATE
, donde las filas adicionales unidas a la actualización son visibles para RETURNING
cláusula:
- Devolver valores de columna previos a la ACTUALIZACIÓN usando solo SQL:versión de PostgreSQL
Lo mismo es actualmente no posible para INSERT
. Por documentación:
La expresión puede usar cualquier nombre de columna de la tabla nombrada por table_name
nombre_tabla siendo el objetivo de INSERT
comando.
Puede usar CTE (de modificación de datos) para que esto funcione.
Suponiendo que title
ser único por consulta , de lo contrario, debe hacer más:
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
no es único por consulta (pero al menos id
es único por tabla):
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);
Esta segunda consulta se basa en el detalle de implementación no documentado de que las filas se insertan en el orden proporcionado. Funciona en todas las versiones actuales de Postgres y probablemente no se rompa.
Violín SQL.