6

Postgres 9.0 は、一般的な一意の制約 ( http://www.postgresql.org/docs/9.0/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE ) に似た除外制約をサポートしています。

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

問題は次のとおりです。次のようなテーブルがあります。

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

user_id一意ごとに 1 つの行のみが"primary"trueになるようにしたいと考えています。次のような除外制約を使用しようとしました。

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

Postgres は次のように拒否しました。

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

それはうまくいきませんでした。&(bit,bit)演算子クラスの一部ではないようです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を見ると、bit_ops順序比較演算子 (>,<,=,>=,<= ) であり、ビット単位の演算子ではありません。なぜそうなのか、よくわかりません。

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

助けてくれてありがとう!

4

1 に答える 1

14

そのための部分的な一意のインデックスを作成する方が簡単なはずです。

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

(この回答と直交していますが、エラーメッセージについて質問しているため、除外制約については、 btree 演算子で使用するためにbtree_ginまたは拡張機能を追加する必要があります。)btree_gist

于 2013-06-20T14:20:37.977 に答える