Вярно е, както беше отбелязано, че RETURNING
клауза на INSERT
вижда само вмъкнатия ред. По-конкретно, цитирайки ръководството тук :
Удебелен акцентът е мой.
Така че нищо не ви пречи да добавите корелирана подзаявка към RETURNING
списък:
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;
Това също е много по-ефективно отколкото заявката, която сте имали (или това, което е било предложено) поради множество причини.
-
Ние не изпълняваме подзаявките
ee
иep
над всички редове на таблицитеemployees.emails
иemployees.profiles
. Това би било ефективно, ако имаме нужда от основни части от тези таблици, но извличаме само един интересен ред от всяка. С подходящи индекси корелирана подзаявка е много по-ефективна за това. Вижте: -
Ние не добавяме режийни разходи за един или повече CTE.
-
Извличаме допълнителни данни само след успешно
INSERT
, така че не се губи време, ако вложката не е преминала по някаква причина. (Вижте цитата в горната част!)
Освен това, вероятно най-важното, това е правилно . Ние използваме данни от реда, който действително е бил вмъкнат -след поставяйки го. (Вижте цитата в горната част!) След като бъдат приложени възможните стойности по подразбиране, задействания или правила. Можем да сме сигурни, че това, което виждаме, е това, което действително е в базата данни (в момента).
Нямате ORDER BY
за profiles.name_first
. Това не е правилно. Или има само един квалифициращ ред, тогава нямаме нужда от DISTINCT
нито LIMIT 1
. Или може да има няколко, тогава се нуждаем и от детерминистичен ORDER BY
за да получите детерминистичен резултат.
И ако emails.t
може да бъде NULL, ще искате да добавите NULLS LAST
в ORDER BY
клауза. Вижте:
Индекси
В идеалния случай имате тези многоколонни индекси (с колони в този ред):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
След това, ако масите са достатъчно вакуумирани, получавате три сканирания само за индекси и цялата операция е светкавична.
Вземете предварително INSERT
ценности?
Ако наистина искате това (което не мисля, че искате), помислете за: