Es cierto, como se ha señalado, que el RETURNING
cláusula de un INSERT
solo ve la fila insertada. Más específicamente, citando el manual aquí :
Negrita énfasis mío.
Así que nada le impide agregar una subconsulta correlacionada al 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;
Esto también es mucho más eficiente que la consulta que tenía (o lo que se propuso) por múltiples razones.
-
No ejecutamos las subconsultas
ee
yep
sobre todas las filas de las tablasemployees.emails
yemployees.profiles
. Eso sería eficiente si necesitáramos partes importantes de esas tablas, pero solo obtenemos una sola fila de interés de cada una. Con índices apropiados, una subconsulta correlacionada es mucho más eficiente para esto. Ver: -
No sumamos los gastos generales de uno o más CTE.
-
Solo obtenemos datos adicionales después un
INSERT
exitoso , por lo que no se pierde tiempo si la inserción no se realizó por algún motivo. (¡Vea la cita en la parte superior!)
Además, posiblemente lo más importante, esto es correcto . Usamos datos de la fila que realmente se ha insertado - después insertándolo. (¡Vea la cita en la parte superior!) Después de que se hayan aplicado los posibles valores predeterminados, activadores o reglas. Podemos estar seguros de que lo que vemos es lo que realmente está en la base de datos (actualmente).
No tienes ORDER BY
para profiles.name_first
. Eso no está bien. O solo hay una fila de calificación, entonces no necesitamos DISTINCT
ni LIMIT 1
. O puede haber varios, entonces también necesitamos un ORDER BY
determinista para obtener un resultado determinista.
Y si emails.t
puede ser NULL, querrá agregar NULLS LAST
en el ORDER BY
cláusula. Ver:
Índices
Idealmente, tiene estos índices de varias columnas (con columnas en este orden):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
Luego, si las tablas se aspiran lo suficiente, obtiene tres escaneos de solo índice y toda la operación es más rápida.
Obtener pre-INSERT
valores?
Si realmente quieres eso (que no creo que quieras), considera: