2013-06-20 29 views
5

Postgres 9.0 hỗ trợ các ràng buộc loại trừ, giống như một ràng buộc duy nhất chung (http://www.postgresql.org/docs/9.0/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE).Tôi làm cách nào để sử dụng ràng buộc Postgres EXCLUDE để ngăn chặn chèn hai hàng chính?

Tôi nhận thấy đây có thể là một cách hay để giải quyết vấn đề này, nhưng tôi không thể tìm ra cách sử dụng các ràng buộc loại trừ một cách chính xác.

Dưới đây là các vấn đề: Tôi có một bảng như thế này:

CREATE TABLE emails (
    id integer NOT NULL, 
    email character varying(255), 
    "primary" boolean DEFAULT false, 
    user_id integer, 
); 

tôi muốn đảm bảo rằng chỉ có một hàng cho mỗi độc đáo user_id"primary" bằng true. Tôi cố gắng để sử dụng một hạn chế loại trừ như thế này:

ALTER TABLE emails ADD CONSTRAINT one_primary_email_per_user EXCLUDE USING gist (user_id WITH =, "primary" WITH &); 

Postgres từ chối rằng với:

ERROR: data type boolean has no default operator class for access method "gist" 
HINT: You must specify an operator class for the index or define a default operator class for the data type. 

tôi đã cố gắng một lần nữa đúc cột boolean để bit:

ALTER TABLE emails ADD CONSTRAINT one_primary_email_per_user EXCLUDE (user_id WITH =, (case "primary" when 't' then '1'::bit else '0'::bit end) WITH &); 

Đó không công việc. Có vẻ như &(bit,bit) không phải là một phần của lớp điều hành bit_ops:

ERROR: operator &(bit,bit) is not a member of operator family "bit_ops" 
DETAIL: The exclusion operator must be related to the index operator class for the constraint. 

Nhìn vào http://www.leadum.com/downloads/dbscribe/samples/postgresql/web_modern/opclass/main/790197862.html, nó có vẻ như bit_ops chỉ bao gồm các lệnh cho toán tử so sánh (>, <, =,> =, < =) và không Bitwise nhà khai thác. Tôi không thực sự chắc chắn tại sao lại như vậy.

Loại loại trừ này có thể có ràng buộc EXCLUDE không? Có cách nào tốt hơn để làm điều này?

Cảm ơn sự giúp đỡ!

Trả lời

11

Nó phải là đơn giản hơn để tạo ra một chỉ số duy nhất một phần cho rằng:

create unique index on emails(email) where (primary); 

(Orthogonal câu trả lời này, nhưng kể từ khi bạn đang hỏi về các thông báo lỗi: cho loại trừ hạn chế, bạn muốn để thêm các tiện ích mở rộng btree_gin hoặc btree_gist để sử dụng với các nhà khai thác btree.)

+2

Ah, cảm ơn! Đây thực sự là những gì tôi đã làm: 'tạo chỉ mục duy nhất trên email (user_id) trong đó (" primary ");' và 'tạo chỉ mục duy nhất trên email (email);'. –

Các vấn đề liên quan