PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

RETURNING powoduje błąd:brak wpisu klauzuli FROM dla tabeli

Prawdą jest, jak zauważono, że RETURNING klauzula INSERT widzi tylko wstawiony wiersz. Dokładniej, cytując instrukcję tutaj :

Pogrubienie nacisk na moje.
Więc nic nie stoi na przeszkodzie, aby dodać skorelowane podzapytanie do 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;

Jest to również znacznie wydajniejsze niż zapytanie, które miałeś (lub co zostało zaproponowane) z wielu powodów.

Dodatkowo, być może najważniejsze, jest to poprawne . Używamy danych z wiersza, który został faktycznie wstawiony - po wkładając go. (Patrz cytat na górze!) Po możliwych wartościach domyślnych zastosowano wyzwalacze lub reguły. Możemy być pewni, że to, co widzimy, jest tym, co faktycznie znajduje się w bazie danych (obecnie).

Nie masz ORDER BY dla profiles.name_first . To nie tak. Albo istnieje tylko jeden kwalifikujący się wiersz, nie potrzebujemy DISTINCT ani LIMIT 1 . Lub może być ich wiele, wtedy potrzebujemy również deterministycznego ORDER BY aby uzyskać deterministyczny wynik.

A jeśli emails.t może być NULL, będziesz chciał dodać NULLS LAST w ORDER BY klauzula. Zobacz:

Indeksy

W idealnym przypadku masz te indeksy wielokolumnowe (z kolumnami w tej kolejności):

  • users (empl_user_pub_uuid, empl_user_pvt_uuid)
  • emails (empl_user_pvt_uuid, email)
  • profiles (empl_user_pvt_uuid, name_first)

Następnie, jeśli tabele są wystarczająco odkurzone, otrzymujesz trzy skany zawierające tylko indeksy, a cała operacja przebiega szybko.

Pobierz pre-INSERT wartości?

Jeśli naprawdę tego chcesz (co nie sądzę), rozważ:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Laravel 5 aktualizuje limit pojedynczych wierszy nie działa

  2. Surowe zapytanie Railsowe dla formatu csv, które ma zostać zwrócone przez kontroler

  3. Dlaczego najbardziej naturalne zapytanie (tj. użycie INNER JOIN (zamiast LEFT JOIN)) jest bardzo wolne

  4. Jak zwrócić wyniki zapytania jako listę oddzieloną przecinkami w PostgreSQL

  5. BŁĄD:ciąg w niekończonym cudzysłowie w miejscu lub w pobliżu