Sự thật, như đã được lưu ý, rằng RETURNING
mệnh đề của một INSERT
chỉ nhìn thấy hàng được chèn. Cụ thể hơn, trích dẫn sách hướng dẫn tại đây :
In đậm nhấn mạnh của tôi.
Vì vậy, không có gì ngăn bạn thêm truy vấn con tương quan đến RETURNING
danh sách:
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;
Điều này cũng hiệu quả hơn nhiều so với truy vấn bạn có (hoặc những gì đã được đề xuất) vì nhiều lý do.
-
Chúng tôi không chạy các truy vấn con
ee
vàep
trên tất cả các hàng của bảngemployees.emails
vàemployees.profiles
. Điều đó sẽ hiệu quả nếu chúng tôi cần các phần chính của các bảng đó, nhưng chúng tôi chỉ lấy một hàng quan tâm từ mỗi bảng. Với các chỉ mục thích hợp, một truy vấn con tương quan sẽ hiệu quả hơn nhiều cho việc này. Xem: -
Chúng tôi không thêm chi phí của một hoặc nhiều CTE.
-
Chúng tôi chỉ tìm nạp thêm dữ liệu sau
INSERT
thành công , vì vậy sẽ không lãng phí thời gian nếu phần chèn không được thực hiện vì bất kỳ lý do gì. (Xem báo giá ở trên cùng!)
Thêm vào đó, có thể là quan trọng nhất, điều này chính xác . Chúng tôi sử dụng dữ liệu từ hàng đã thực sự được chèn - sau chèn nó. (Xem phần trích dẫn ở trên cùng!) Sau khi các giá trị mặc định có thể có, các trình kích hoạt hoặc quy tắc đã được áp dụng. Chúng tôi có thể chắc chắn rằng những gì chúng tôi thấy là những gì thực sự có trong cơ sở dữ liệu (hiện tại).
Bạn không có ORDER BY
cho profiles.name_first
. Điều đó không đúng. Hoặc chỉ có một hàng đủ điều kiện, thì chúng ta không cần DISTINCT
cũng không phải LIMIT 1
. Hoặc có thể có nhiều, thì chúng ta cũng cần một ORDER BY
xác định để có được kết quả xác định.
Và nếu emails.t
có thể là NULL, bạn sẽ muốn thêm NULLS LAST
trong ORDER BY
mệnh đề. Xem:
Chỉ mục
Lý tưởng nhất là bạn có các chỉ mục đa cột này (với các cột theo thứ tự này):
-
users (empl_user_pub_uuid, empl_user_pvt_uuid)
-
emails (empl_user_pvt_uuid, email)
-
profiles (empl_user_pvt_uuid, name_first)
Sau đó, nếu các bảng được hút bụi đủ, bạn sẽ nhận được ba lần quét chỉ mục và toàn bộ hoạt động sẽ nhanh chóng sáng sủa.
Nhận trước INSERT
giá trị?
Nếu bạn thực sự muốn điều đó (mà tôi không nghĩ bạn làm vậy), hãy xem xét: