Tôi nhớ đã nêu ra một điểm gần như giống hệt nhau khi PG9 ở trạng thái alpha. Đây là câu trả lời từ Tom Lane (nhà phát triển cốt lõi PG nổi tiếng):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
Tóm lại:sẽ không sửa được.
Không có nghĩa là tôi đồng ý với đề xuất của bạn rằng hành vi hiện tại là một lỗi. Hãy nhìn nó từ một góc độ ngược lại:đó là hành vi của NOT DEFERRABLE
điều đó không chính xác.
Trên thực tế, vi phạm ràng buộc trong CẬP NHẬT này sẽ không bao giờ xảy ra trong mọi trường hợp, vì ở cuối CẬP NHẬT, ràng buộc đã được thỏa mãn. Trạng thái ở cuối lệnh mới là điều quan trọng. Các trạng thái trung gian trong quá trình thực thi một câu lệnh đơn lẻ sẽ không được hiển thị cho người dùng.
Có vẻ như PostgreSQL thực hiện ràng buộc không thể trì hoãn bằng cách kiểm tra các bản sao sau mỗi hàng được cập nhật và không thành công ngay khi bản sao đầu tiên, điều này về cơ bản là thiếu sót. Nhưng đây là một vấn đề đã biết, có thể là cũ như PostgreSQL. Ngày nay, giải pháp cho vấn đề này chính xác là sử dụng ràng buộc DEFERRABLE. Và có một số điều trớ trêu là bạn đang nhìn nó như thiếu hụt vì nó không thành công, trong khi bằng cách nào đó nó được cho là giải pháp cho sự thất bại ngay từ đầu!
Tóm tắt hiện trạng kể từ PostgreSQL 9.1
-
NOT DEFERRABLE
UNIQUE
hoặcPRIMARY KEY
các ràng buộc được chọn sau mỗi hàng . -
DEFERRABLE
các ràng buộc được đặt thànhIMMEDIATE
(INITIALLY IMMEDIATE
hoặc quaSET CONSTRAINTS
) được chọn sau mỗi câu lệnh . -
DEFERRABLE
các ràng buộc được đặt thànhDEFERRED
(INITIALLY DEFERRED
hoặc quaSET CONSTRAINTS
) được kiểm tra sau mỗi giao dịch .
Lưu ý cách xử lý đặc biệt của UNIQUE
/ PRIMARY KEY
Các ràng buộc. Trích dẫn trang thủ công cho CREATE TABLE
:
Ràng buộc không thể hoãn lại sẽ được kiểm tra ngay lập tức sau mỗi lệnh .
Trong khi nó nói rõ hơn trong phần Khả năng tương thích trong Non-deferred uniqueness constraints
:
Khi một
UNIQUE
hoặcPRIMARY KEY
ràng buộc không thể trì hoãn, PostgreSQL kiểm tra tính duy nhất ngay lập tức bất cứ khi nào một hàng được chèn hoặc sửa đổi. Tiêu chuẩn SQL nói rằng tính duy nhất phải được bắt buộc chỉ ở cuối câu lệnh ; điều này tạo ra sự khác biệt, chẳng hạn như khi một lệnh duy nhất cập nhật nhiều giá trị khóa. Để đạt được hành vi tuân thủ tiêu chuẩn, hãy khai báo ràng buộc làDEFERRABLE
nhưng không được hoãn lại (tức làIMMEDIATE
). Hãy lưu ý rằng điều này có thể chậm hơn đáng kể so với việc kiểm tra tính duy nhất ngay lập tức.
Nhấn mạnh đậm của tôi.
Nếu bạn cần bất kỳ FOREIGN KEY
nào ràng buộc để tham chiếu (các) cột, DEFERRABLE
không phải là một tùy chọn vì (theo tài liệu):
Các cột được tham chiếu phải là các cột của ràng buộc khóa chính duy nhất không thể trì hoãn hoặc khóa chính trong bảng được tham chiếu.