È 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
ee
eep
su tutte le righe delle tabelleemployees.emails
eemployees.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
INSERT
riuscito , 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: