Byłoby to prostsze dla UPDATE
, gdzie dodatkowe wiersze dołączone do aktualizacji są widoczne dla RETURNING
klauzula:
- Zwróć wartości kolumn sprzed AKTUALIZACJI, używając tylko SQL — wersja PostgreSQL
To samo jest obecnie nie możliwe dla INSERT
. Zgodnie z dokumentacją:
Wyrażenie może używać dowolnych nazw kolumn tabeli nazwanej przez nazwa_tabeli
nazwa_tabeli będąc celem INSERT
polecenie.
Aby to zadziałało, możesz użyć (modyfikowania danych) CTE.
Zakładając title
być unikatowym dla każdego zapytania , w przeciwnym razie musisz zrobić więcej:
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);
Jeśli title
nie jest unikalny na zapytanie (ale przynajmniej id
jest unikalny na każdy stół):
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);
To drugie zapytanie opiera się na nieudokumentowanych szczegółach implementacji, w których wiersze są wstawiane w podanej kolejności. Działa we wszystkich aktualnych wersjach Postgresa i prawdopodobnie się nie zepsuje.
Skrzypce SQL.