É 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 subconsultaseeeepem todas as linhas das tabelasemployees.emailseemployees.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 umINSERTbem-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: