2013-06-20 11 views
5

Postgres 9.0, genel benzersiz bir kısıtlama (http://www.postgresql.org/docs/9.0/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) gibi bir tür dışlama kısıtlamalarını destekler. İki birincil satırın eklenmesini önlemek için Postgres EXCLUDE kısıtlamasını nasıl kullanabilirim?

ben bu sorunu çözmek için iyi bir yol olabileceğini düşündüm, ama düzgün dışlama kısıtlamaları nasıl kullanılacağını anlamaya olamaz.

Burada sorun: Böyle bir tablo var:

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

Ben benzersiz user_id başına yalnızca bir satır true eşit "primary" sahip olmasını sağlamak istiyoruz. Denedim

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. 

tekrar bit için boolean sütun döküm:

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 &); 

vermedi Yani

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

Postgres o reddetti: Böyle bir dışlama kısıtlamayı kullanmaya çalıştı iş. Bu &(bit,bit) operatör sınıfının bit_ops parçası değildir görünüyor: bit_ops sadece sipariş karşılaştırma operatörlerini kapsamaktadır gibi

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. 

http://www.leadum.com/downloads/dbscribe/samples/postgresql/web_modern/opclass/main/790197862.html baktığımızda, öyle görünüyor (>, <, =,> =, < =) değil operatörleri bitsel. Bunun neden böyle olduğundan emin değilim.

bir EXCLUDE kısıtlaması ile olası dışlanma bu tür mı? Bunu yapmanın daha iyi bir yolu var mı?

Yardımın için teşekkürler!

cevap

11

O için kısmi benzersiz bir dizin oluşturmak için basit olmalıdır: Hata iletisi hakkında soruyorsun beri bu cevaba

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

(Ortogonal ama: kısıtlamayı hariç için, istediğiniz ediyorum btree operatörleri ile kullanılmak üzere btree_gin veya btree_gist uzantılar eklemek.)

+2

Ah, teşekkürler! Bu aslında yaptığım şudur: 'e-postalarda (user_id) benzersiz bir dizin yaratın (user_id) burada (" birincil ") ve' e-postalarda benzersiz e-posta (e-posta) oluşturun. –

İlgili konular