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.
-
Nie uruchamiamy podzapytań
ee
iep
we wszystkich wierszach tabelemployees.emails
iemployees.profiles
. Byłoby to efektywne, gdybyśmy potrzebowali większej części tych tabel, ale z każdej pobieramy tylko jeden wiersz zainteresowania. Przy odpowiednich indeksach skorelowane podzapytanie jest do tego znacznie wydajniejsze. Zobacz: -
Nie dodajemy narzutu jednego lub więcej CTE.
-
Dodatkowe dane pobieramy dopiero po udane
INSERT
, więc nie marnujesz czasu, jeśli wkładka nie została z jakiegoś powodu przeszła. (Patrz cytat u góry!)
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ż: