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我想确保每个唯一的只有一行"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_ginorbtree_gist扩展以与 btree 运算符一起使用。)

于 2013-06-20T14:20:37.977 回答