sql >> Base de Datos >  >> RDS >> PostgreSQL

RETURNANDO provoca un error:falta la entrada de la cláusula FROM para la tabla

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.

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: