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.