Postgresql postgres中相对于其他行的部分唯一索引

Postgresql postgres中相对于其他行的部分唯一索引,postgresql,unique-constraint,Postgresql,Unique Constraint,一般来说,我知道PostgreSQL中有部分唯一索引,但我需要加入一个约束,我认为它不适合部分索引领域。或者也许有一种表达方式 最小示例 CREATE TABLE table (user INT, type INT, flag BOOL, text VARCHAR (50)); 这些要求是: 用户可以有多行相同的类型,但前提是标志为false 如果用户有一行具有特定类型和标志设置为true,则该用户和类型不能有其他行 例如,如果表中有以下行: | user | type | flag | t

一般来说,我知道PostgreSQL中有部分唯一索引,但我需要加入一个约束,我认为它不适合部分索引领域。或者也许有一种表达方式

最小示例

CREATE TABLE table (user INT, type INT, flag BOOL, text VARCHAR (50));
这些要求是:

  • 用户
    可以有多行相同的
    类型
    ,但前提是
    标志
    为false

  • 如果
    用户
    有一行具有特定
    类型
    标志
    设置为true,则该
    用户
    类型
    不能有其他行

  • 例如,如果表中有以下行:

    | user | type | flag  | text |
    | 1    | 1    | false | foo  |
    | 1    | 1    | false | bar  |
    
    然后我们不能插入(1,1,true,'whatever')


    此外,如果表中包含:

    | user | type | flag | text |
    | 1    | 1    | true | foo  |
    
    我们不能插入(1,1,false,'bar')或(1,1,true,'baz'))



    在PostgreSQL中有没有一种方法可以表达这样的约束?

    您需要a和a的组合。不幸的是,在排除约束中没有可用于布尔列的运算符族,因此可以使用整数列。需要为整型列模拟gist索引

    create extension if not exists btree_gist;
    
    表定义(标识符稍微修改):

    drop table if exists my_table;
    create table my_table (
        user_id integer,
        type_id integer, 
        flag integer check (flag in (0, 1)),
        text varchar (50),
        exclude using gist (user_id with =, type_id with =, flag with <>)
    );
    
    create unique index on my_table (user_id, type_id) where flag = 1;
    
    insert into my_table
    values
    (1, 1, 0, 'foo'),
    (1, 1, 0, 'bar'),
    (2, 2, 1, 'foo');
    
    INSERT 0 3
    
    insert into my_table
    values
    (1, 1, 1, 'whatever');
    
    ERROR:  conflicting key value violates exclusion constraint "my_table_user_id_type_id_flag_excl"
    DETAIL:  Key (user_id, type_id, flag)=(1, 1, 1) conflicts with existing key (user_id, type_id, flag)=(1, 1, 0).
    
    insert into my_table
    values
    (2, 2, 0, 'whatever');
    
    ERROR:  conflicting key value violates exclusion constraint "my_table_user_id_type_id_flag_excl"
    DETAIL:  Key (user_id, type_id, flag)=(2, 2, 0) conflicts with existing key (user_id, type_id, flag)=(2, 2, 1).
    
    insert into my_table
    values
    (2, 2, 1, 'whatever');
    
    ERROR:  duplicate key value violates unique constraint "my_table_user_id_type_id_idx"
    DETAIL:  Key (user_id, type_id)=(2, 2) already exists.