【问题标题】:mysql constraint unique when boolean field is true当布尔字段为真时,mysql约束唯一
【发布时间】:2025-12-28 09:45:11
【问题描述】:

我有这张桌子:

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

但我无法弄清楚我需要添加的限制条件是每个国家/地区只有一名主要专家

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

【问题讨论】:

  • constraint unique (country_id, main) 怎么样。所以你只能让每个国家都有真正的
  • 如果他们不是主要的,我可以为一个国家有很多专家。 每个国家/地区只有一名主要 (=true) 专家

标签: mysql sql unique-constraint


【解决方案1】:

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

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

main boolean null default null,
constraint unique index uidx_expert_country (country_id, main)

这可能需要更改您的应用程序,可能看起来很粗略(因为 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)

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

【讨论】:

  • 我选择了main_unq dummy column 解决方案,效果很好。谢谢。