2013-06-20 14 views
5

PostgreSQL 9.0は排他制約をサポートしています。これは一般的な一意制約(http://www.postgresql.org/docs/9.0/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE)のようなものです。Postgres EXCLUDE制約を使用して2つのプライマリ行を挿入しないようにするにはどうすればよいですか?

これはこの問題を解決するのには良い方法だとわかりましたが、除外の制約を適切に使用する方法を理解できません。ここで

は問題です: 私はこのようなテーブルを持っている:

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

私はユニークuser_idごとに1つだけの行がtrueに等しい"primary"を持っていることを確認します。私が試した

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. 

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

なかったこと

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

Postgresはしていることを拒否した:私はこのような排他制約を使用してみました作業。それは&(bit,bit)は、演算子クラスbit_opsの一部ではないようだ。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. 

http://www.leadum.com/downloads/dbscribe/samples/postgresql/web_modern/opclass/main/790197862.htmlを見ると、それはそう(>、<、=、> =、< =)とないビット演算子。なぜそれが本当にわからないのですか?

この種の除外はEXCLUDE制約で可能ですか?これを行うより良い方法はありますか?

ありがとうございました!

答えて

11

そのための部分的な一意のインデックスを作成する方が簡単でなければなりません:あなたは、エラーメッセージについて尋ねているので、この回答へ

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

(直交を、しかし:制約を除外するために、あなたがしたいと思います)btree_ginまたはbtree_gistの拡張子をbtreeオペレータで使用するために追加してください。

+2

ああ、ありがとう!これは実際に私がやったことです: '電子メールにユニークなインデックスを作成する(user_id)ここで("プライマリ ");および'電子メール(電子メール)にユニークなインデックスを作成する; –

関連する問題