PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

RETURNING causa erro:falta de entrada da cláusula FROM para a tabela


É 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.

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: