La clausola 'return' può restituire colonne di origine che non sono state inserite?


14

Ecco un esempio minimo del mio problema nel mondo reale:

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

ovviamente puoi restituire le colonne inserite con una returningclausola:

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

puoi anche restituire un valore letterale:

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 |
*/

ma non puoi restituire le colonne di origine:

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
*/

Esiste un modo per uscire w.rnddalla returningclausola finale ?

db <> violino qui


In MS SQL Server solo l'istruzione MERGE consente di restituire colonne aggiuntive. Forse funzionerà anche per Postgres.
— Sebastian Meine,

Ho risolto un problema simile per UPDATEquesta risposta correlata su SO , ma per questo non funzionerà INSERT.
— Erwin Brandstetter,

Risposte:


12

La documentazione sulla RETURNINGclausola dice:

Un'espressione da calcolare e restituire dal comando INSERT dopo aver inserito ogni riga. L'espressione può utilizzare qualsiasi nome di colonna della tabella denominata da table_name. Scrivi * per restituire tutte le colonne delle righe inserite.

Ciò chiaramente non si applica alle colonne di un'altra tabella.

Anche se non capisco davvero il problema (ovvero perché lo fai - immagino che sia perché è una versione un po 'troppo astratta di quella originale), una possibile soluzione può essere:

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;

In altre parole, è possibile inserire più di un CTE scrivibile all'inizio di una query. Si prega di vedere questo in azione su dbfiddle .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.