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
eedanepatas semua baris tabelemployees.emailsdanemployees.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
INSERTsuccessful 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: