Việc triển khai UPSERT cực kỳ phức tạp để đảm bảo an toàn trước quyền truy cập ghi đồng thời. Hãy xem Postgres Wiki này được dùng làm nhật ký trong quá trình phát triển ban đầu. Tin tặc Postgres quyết định không đưa các hàng "bị loại trừ" vào RETURNING
điều khoản cho bản phát hành đầu tiên trong Postgres 9.5. Họ có thể xây dựng một cái gì đó cho bản phát hành tiếp theo.
Đây là tuyên bố quan trọng trong sổ tay hướng dẫn để giải thích tình huống của bạn:
Cú pháp của
RETURNING
danh sách giống với danh sách đầu ra củaSELECT
. Chỉ những hàng đã được chèn hoặc cập nhật thành công sẽ được trả lại. Ví dụ:nếu một hàng đã bị khóa nhưng không được cập nhật bởi vìON CONFLICT DO UPDATE ... WHERE
điều kiện mệnh đề không được thỏa mãn, hàng sẽ không được trả lại.
Nhấn mạnh đậm của tôi.
Đối với một hàng đơn để chèn:
Không có tải ghi đồng thời trên cùng một bảng
WITH ins AS (
INSERT INTO users(name)
VALUES ('new_usr_name') -- input value
ON CONFLICT(name) DO NOTHING
RETURNING users.id
)
SELECT id FROM ins
UNION ALL
SELECT id FROM users -- 2nd SELECT never executed if INSERT successful
WHERE name = 'new_usr_name' -- input value a 2nd time
LIMIT 1;
Có thể có tải ghi đồng thời trên bảng
Thay vào đó, hãy xem xét điều này (đối với hàng đơn INSERT
):
- CHỌN hoặc CHÈN trong một hàm có nguy cơ gặp phải các điều kiện về chủng tộc không?
Để chèn một tập hợp các hàng :
-
Làm thế nào để sử dụng RETURNING với ON CONFLICT trong PostgreSQL?
-
Làm thế nào để bao gồm các hàng bị loại trừ trong QUAY LẠI khỏi CHÈN ... BẬT MANG TÍNH
Cả ba đều có giải thích rất chi tiết.