PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

INSERT INTO ... FROM SELECT ... RETURNING ID-Zuordnungen

Dies wäre einfacher für UPDATE , wobei zusätzliche Zeilen, die in das Update aufgenommen wurden, für RETURNING sichtbar sind Klausel:

  • Spaltenwerte vor dem UPDATE nur mit SQL zurückgeben – PostgreSQL-Version

Das Gleiche gilt derzeit nicht möglich für INSERT . Per Dokumentation:

Der Ausdruck kann beliebige Spaltennamen der durch table_name benannten Tabelle verwenden

Tabellenname das Ziel von INSERT ist Befehl.

Sie können (datenmodifizierende) CTEs verwenden, um dies zum Laufen zu bringen.
Angenommen title eindeutig pro Abfrage sein , sonst müssen Sie mehr tun:

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

Wenn title ist nicht pro Abfrage eindeutig (aber mindestens id ist pro Tabelle eindeutig):

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

Diese zweite Abfrage stützt sich auf das undokumentierte Implementierungsdetail, dass Zeilen in der angegebenen Reihenfolge eingefügt werden. Es funktioniert in allen aktuellen Versionen von Postgres und wird wahrscheinlich nicht kaputt gehen.

SQL-Geige.