Bisakah 'kembali' klausa kolom kembali sumber yang tidak dimasukkan?


14

Inilah contoh minimal masalah dunia nyata saya:

create table t(id serial primary key, rnd double precision);

tentu saja Anda dapat mengembalikan kolom yang disisipkan dengan returningklausa:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *;
/*
| ID |            RND |
|----|----------------|
|  9 | 0.203221440315 |
*/

Anda juga dapat mengembalikan literal:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *, 1.0 dummy;
/*
| ID |            RND | DUMMY |
|----|----------------|-------|
| 11 | 0.594980469905 |     1 |
*/

tetapi Anda tidak dapat mengembalikan kolom sumber:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *, w.rnd;
/*
ERROR: missing FROM-clause entry for table "w": with w as (insert into t(rnd) values(random()) returning *) insert into t(rnd) select random() from w returning *, w.rnd
*/

Apakah ada cara saya bisa w.rndkeluar dari returningklausa terakhir ?

db <> biola di sini


Dalam MS SQL Server hanya pernyataan MERGE yang memungkinkan kolom tambahan untuk dikembalikan. Mungkin itu akan berhasil untuk postgres juga.
— Sebastian Meine

Saya memecahkan masalah yang sama UPDATEdalam jawaban terkait ini pada SO , tetapi ini tidak akan berhasil INSERT.
— Erwin Brandstetter

Jawaban:


12

Dokumentasi pada RETURNINGklausa mengatakan:

Ekspresi yang akan dihitung dan dikembalikan oleh perintah INSERT setelah setiap baris dimasukkan. Ekspresi dapat menggunakan nama kolom dari tabel yang dinamai dengan table_name. Tulis * untuk mengembalikan semua kolom dari baris yang dimasukkan.

Ini jelas tidak berlaku untuk kolom dari tabel lain.

Meskipun saya tidak benar-benar mengerti masalahnya (yaitu mengapa Anda melakukan ini - saya bayangkan itu karena versi yang agak terlalu abstrak dari yang asli), solusi yang mungkin adalah:

WITH w AS (INSERT INTO t(rnd) VALUES (random()) RETURNING *),
     x AS (INSERT INTO t(rnd) SELECT random() FROM w RETURNING *)
SELECT w.rnd, x.rnd
  FROM w, x;

Artinya, Anda dapat menempatkan lebih dari satu CTE yang dapat ditulis ke awal kueri. Silakan lihat ini beraksi di dbfiddle .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.