Het is waar, zoals is opgemerkt, dat de RETURNING
clausule van een INSERT
ziet alleen de ingevoegde rij. Meer specifiek, de handleiding hier citerend :
Vet nadruk van mij.
Dus niets weerhoudt u ervan een gecorreleerde subquery toe te voegen naar de RETURNING
lijst:
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;
Dit is ook veel efficiënter dan de vraag die je had (of wat werd voorgesteld) om meerdere redenen.
-
We voeren de subquery's
ee
niet uit enep
over alle rijen van de tabellenemployees.emails
enemployees.profiles
. Dat zou efficiënt zijn als we grote delen van die tabellen nodig hadden, maar we halen uit elk slechts een enkele rij met interesse op. Met de juiste indexen is een gecorreleerde subquery hiervoor veel efficiënter. Zie: -
We tellen de overhead van een of meer CTE's niet op.
-
We halen alleen aanvullende gegevens op na een succesvolle
INSERT
, dus er wordt geen tijd verspild als de insert om welke reden dan ook niet is doorgekomen. (Zie citaat bovenaan!)
En, misschien wel het belangrijkste, dit is correct . We gebruiken gegevens uit de rij die daadwerkelijk is ingevoegd - na het invoegen. (Zie citaat bovenaan!) Nadat eventuele standaardwaarden, triggers of regels zijn toegepast. We kunnen er zeker van zijn dat wat we zien is wat er daadwerkelijk in de database staat (momenteel).
U heeft geen ORDER BY
voor profiles.name_first
. Dat klopt niet. Ofwel is er maar één kwalificatierij, dan hebben we geen DISTINCT
. nodig noch LIMIT 1
. Of er kunnen er meerdere zijn, dan hebben we ook een deterministische ORDER BY
nodig om een deterministisch resultaat te krijgen.
En als emails.t
kan NULL zijn, voeg dan NULLS LAST
toe in de ORDER BY
clausule. Zie:
Indexen
Idealiter heb je deze indexen met meerdere kolommen (met kolommen in deze volgorde):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
Als de tafels voldoende zijn gestofzuigd, krijgt u drie scans met alleen index en wordt de hele operatie een fluitje van een cent.
Verkrijg pre-INSERT
waarden?
Als je dat echt wilt (wat volgens mij niet het geval is), overweeg dan: