È 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.
-
Non eseguiamo le sottoquery
eeeepsu tutte le righe delle tabelleemployees.emailseemployees.profiles. Sarebbe efficiente se avessimo bisogno delle parti principali di quelle tabelle, ma recuperiamo solo una singola riga di interesse da ciascuna. Con indici appropriati, una sottoquery correlata è molto più efficiente per questo. Vedi: -
Non aggiungiamo l'overhead di uno o più CTE.
-
Recuperiamo dati aggiuntivi solo dopo un
INSERTriuscito , quindi non si perde tempo se l'inserto non è andato a buon fine per qualsiasi motivo. (Vedi citazione in alto!)
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 DISTINCT né LIMIT 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: