PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

RETURNING provoca l'errore:manca la voce della clausola FROM per la tabella

È vero, come è stato notato, che il RETURNING clausola di un INSERT vede solo la riga inserita. Più specificamente, citando il manuale qui :

Grassetto enfasi mia.
Quindi nulla ti impedisce di aggiungere una sottoquery correlata al RETURNING elenco:

INSERT INTO employees.password_resets AS ep
       (empl_pwd_reset_uuid                  , empl_user_pvt_uuid                    , t_valid                     , for_empl_user_pvt_uuid, token)
SELECT 'f70a0346-a077-11eb-bd1a-aaaaaaaaaaaa', '6efc2b7a-f27e-11ea-b66c-de1c405de048', '2021-04-18 19:57:47.111365', eu.empl_user_pvt_uuid , '19d65aea-7c4a-41bc-b580-9d047f1503e6'
FROM   employees.users eu
WHERE  empl_user_pub_uuid = 'e2bb39f1f28011eab66c63cb4d9c7a34'
RETURNING for_empl_user_pvt_uuid AS empl_user_pvt_uuid  -- alias to meet your org. query
        , (SELECT email
           FROM   employees.emails
           WHERE  empl_user_pvt_uuid = ep.empl_user_pvt_uuid
           ORDER  BY t DESC  -- NULLS LAST ?
           LIMIT  1
          ) AS email
        , (SELECT name_first
           FROM   employees.profiles
           WHERE  empl_user_pvt_uuid = ep.empl_user_pvt_uuid
           -- ORDER  BY ???
           LIMIT  1
          ) AS name_first;

Questo è anche molto più efficiente rispetto alla domanda che avevi (o a ciò che ti è stato proposto) per molteplici motivi.

Inoltre, forse la cosa più importante, questo è corretto . Utilizziamo i dati della riga effettivamente inserita - dopo inserendolo. (Vedi la citazione in alto!) Dopo che sono stati applicati possibili valori predefiniti, trigger o regole. Possiamo essere certi che ciò che vediamo è ciò che è effettivamente nel database (attualmente).

Non hai ORDER BY per profiles.name_first . Non è giusto. O c'è solo una riga qualificante, quindi non abbiamo bisogno di DISTINCTLIMIT 1 . Oppure possono essercene multipli, quindi abbiamo anche bisogno di un deterministico ORDER BY per ottenere un risultato deterministico.

E se emails.t può essere NULL, ti consigliamo di aggiungere NULLS LAST nel ORDER BY clausola. Vedi:

Indici

Idealmente, hai questi indici multicolonna (con colonne in questo ordine):

  • users (empl_user_pub_uuid, empl_user_pvt_uuid)
  • emails (empl_user_pvt_uuid, email)
  • profiles (empl_user_pvt_uuid, name_first)

Quindi, se i tavoli vengono aspirati a sufficienza, si ottengono tre scansioni solo indice e l'intera operazione si alleggerisce rapidamente.

Ottieni il pre-INSERT valori?

Se lo vuoi davvero (cosa che non penso tu voglia), considera: