Memang benar, seperti yang telah dicatat, bahwa RETURNING
klausa dari INSERT
hanya melihat baris yang disisipkan. Lebih khusus lagi, mengutip manual di sini :
Tebal penekanan saya.
Jadi tidak ada yang menghalangi Anda untuk menambahkan subkueri yang berkorelasi ke RETURNING
daftar:
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;
Ini juga jauh lebih efisien daripada kueri yang Anda miliki (atau apa yang diusulkan) karena berbagai alasan.
-
Kami tidak menjalankan subkueri
ee
danep
atas semua baris tabelemployees.emails
danemployees.profiles
. Itu akan efisien jika kami membutuhkan bagian utama dari tabel tersebut, tetapi kami hanya mengambil satu baris yang menarik dari masing-masing tabel. Dengan indeks yang sesuai, subquery yang berkorelasi jauh lebih efisien untuk ini. Lihat: -
Kami tidak menambahkan overhead dari satu atau lebih CTE.
-
Kami hanya mengambil data tambahan setelah
INSERT
successful berhasil , jadi tidak ada waktu yang terbuang jika sisipan tidak masuk karena alasan apa pun. (Lihat kutipan di atas!)
Plus, mungkin yang paling penting, ini benar . Kami menggunakan data dari baris yang sebenarnya telah dimasukkan - setelah memasukkannya. (Lihat kutipan di atas!) Setelah kemungkinan nilai default, pemicu atau aturan diterapkan. Kita dapat yakin bahwa apa yang kita lihat adalah apa yang sebenarnya ada di database (saat ini).
Anda tidak memiliki ORDER BY
untuk profiles.name_first
. Itu tidak benar. Jika hanya ada satu baris kualifikasi, maka kita tidak memerlukan DISTINCT
atau LIMIT 1
. Atau bisa banyak, maka kita juga membutuhkan ORDER BY
deterministik untuk mendapatkan hasil deterministik.
Dan jika emails.t
bisa NULL, Anda ingin menambahkan NULLS LAST
di ORDER BY
ayat. Lihat:
Indeks
Idealnya, Anda memiliki indeks multikolom ini (dengan kolom dalam urutan ini):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
Kemudian, jika tabel cukup disedot, Anda mendapatkan tiga pemindaian indeks saja dan seluruh operasi menjadi lebih cepat.
Dapatkan pra-INSERT
nilai?
Jika Anda benar-benar menginginkannya (yang menurut saya tidak), pertimbangkan: