在其中一列中具有多个空值的复合唯一键约束

Posted

技术标签:

【中文标题】在其中一列中具有多个空值的复合唯一键约束【英文标题】:Composite Unique key constraint with multiple null value in one of the column 【发布时间】:2019-06-14 16:25:41 【问题描述】:

我在表 x 上有一个唯一键,包含 3 列 (a,b,c),其中 a,b,c 是外键,c 在 x 表中可以为空。

a b c
- - ----
1 1    1
1 1    2
1 1 NULL
1 1 NUll

以上行在 mysql 上有效,插入具有多个 null 的行不会违反约束。但对于 Oracle ,SQL-Server 则不是这样

这种情况下的最佳做法是什么?

每个唯一约束都会创建唯一索引,如果我禁用唯一索引,SQL-Server 中也允许多个空值(使用过滤索引)

我需要在 c 列中设置多个值,其中 null 作为其外键。

请建议我应该删除唯一键约束,我应该从表 x 的列 c 中删除外键。或者我们有任何其他解决方案。

【问题讨论】:

在 mysql 中可能允许使用的唯一键和不允许使用的外键,但毫无意义。 我有一个应用程序支持4个数据库 如果你的列不是唯一的,那么你就不能对它们有唯一的约束(或者,至少,在 MySQL 的情况下不应该有一个)。 列是唯一的,但当列值之一为 NULL 时,它不是唯一的。 这不是好事吗?如果 (a,b,c) 有唯一约束,那么添加两个 (1,1,null) 无论如何都会出错? 【参考方案1】:

这个索引做你想做的事:

create unique index idx_t_abc on t(
  case when c is not null then a end,
  case when c is not null then b end, 
  case when c is not null then c end);

仅在 Oracle 中测试。 asktom 网站上的类似问题:unique index with null values.

【讨论】:

【参考方案2】:

在 SQL Server 中,您可以使用过滤索引:

create index unq_t_a_b_c on t(a, b, c)
    where c is not null;

这也应该适用于 Postgres 和 Postgres 派生的数据库。

Oracle 不支持过滤索引。您可以为此目的使用计算列——假设您有一个主键:

create index unq_t_a_b_c on t(a, b, c, (case when c is null then pk end));

c 为空时,这将允许多个值。

【讨论】:

以上是关于在其中一列中具有多个空值的复合唯一键约束的主要内容,如果未能解决你的问题,请参考以下文章

SQL中Unique约束有啥用啊?

SQL中Unique约束有啥用啊?

Sql Server 主键 外键约束

如何创建一个也允许空值的唯一约束?

MySQL 索引

约束的类型