sql >> Base de Datos >  >> RDS >> PostgreSQL

INSERTAR EN... DESDE SELECCIONAR... REGRESAR asignaciones de id

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.