É verdade, como foi observado, que o
RETURNING
cláusula de um INSERT
vê apenas a linha inserida. Mais especificamente, citando o manual aqui :Negrito ênfase minha.
Portanto, nada impede que você adicione uma subconsulta correlacionada para o
RETURNING
Lista: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;
Isso também é muito mais eficiente do que a consulta que você teve (ou o que foi proposto) por vários motivos.
-
Não executamos as subconsultasee
eep
em todas as linhas das tabelasemployees.emails
eemployees.profiles
. Isso seria eficiente se precisássemos de partes importantes dessas tabelas, mas apenas buscamos uma única linha de interesse de cada uma. Com índices apropriados, uma subconsulta correlacionada é muito mais eficiente para isso. Ver:
-
Não adicionamos a sobrecarga de um ou mais CTEs.
-
Só buscamos dados adicionais depois umINSERT
bem-sucedido , portanto, não há perda de tempo se a inserção não for concluída por qualquer motivo. (Veja a citação no topo!)
Além disso, possivelmente o mais importante, isso está correto . Usamos dados da linha que foi realmente inserida - depois inserindo-o. (Veja a cotação no topo!) Após a aplicação de possíveis valores padrão, gatilhos ou regras. Podemos ter certeza de que o que vemos é o que está realmente no banco de dados (atualmente).
Você não tem
ORDER BY
para profiles.name_first
. Isso não está certo. Ou há apenas uma linha de qualificação, então não precisamos de DISTINCT
nem LIMIT 1
. Ou pode haver vários, então também precisamos de um ORDER BY
determinístico obter um resultado determinístico. E se
emails.t
pode ser NULL, você vai querer adicionar NULLS LAST
no ORDER BY
cláusula. Ver:Índices
Idealmente, você tem esses índices de várias colunas (com colunas nesta ordem):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
Então, se as tabelas forem suficientemente limpas, você obtém três varreduras somente de índice e toda a operação é extremamente rápida.
Obter pré-INSERT
valores?
Se você realmente quer isso (o que eu acho que não), considere: