当布尔字段为true时,mysql约束是唯一的

lou*_*ros 5 mysql sql unique-constraint

我有这张桌子:

create table expert_country (
    expert_id  varchar(36) not null,
    country_id varchar(36) not null,
    main       boolean     not null default false,
    primary key (expert_id, country_id),
    constraint foreign key (expert_id) references expert (id),
    constraint foreign key (country_id) references country (id),
    -- constraint i'm looking for
);
Run Code Online (Sandbox Code Playgroud)

但是我无法弄清楚每个国家只有一个主要专家所需要增加的限制。

我试过了constraint unique (country_id, true)constraint unique (*, country_id, true)但是它不是有效的sql。有任何想法吗?

Sol*_*are 6

您可以使用唯一键忽略null(遵循 sql 标准):任何包含的元组null都不等同于任何元组。这意味着,在唯一索引中(country_id, main),您可以(1, null)随心所欲地拥有该行,但最多只有一行(1, 1)和一行(1, 0)

您需要允许nullmain,并需要使用1null(不0)来编码,如果它是一个专家或不(否则你只能有一个非专家)。那么约束将是:

main boolean null default null,
constraint unique index uidx_expert_country (country_id, main)
Run Code Online (Sandbox Code Playgroud)

这可能需要对您的应用程序进行更改,可能看起来很粗略(false显然与 不同null)并且可能会软化您的列的解释(因为它现在可以包含 3 个值null0/false1/true虽然您可以通过额外的外来防止这种情况发生)单行包含1)的表的键。

因此,如果您不想这样做,您可以定义将在触发器中计算或作为生成列的附加列,然后在该“虚拟”列上定义唯一索引:

main boolean  not null default false,
main_unq  boolean as (if(main = true,true, null)) stored,
constraint unique index uidx_expert_country (country_id, main_unq)
Run Code Online (Sandbox Code Playgroud)

对于编码信息的不同方式,哪个专家是一个国家的主要专家,您可以例如main_expert_id在您的country-table 中添加一列(以及一个外键expert_country以验证组合是否存在)并删除该列main