创建唯一复合索引,其中一个字段在Mysql中可以为null

时间:2016-06-12 15:18:38

标签: mysql indexing

我创建了独特的复合指数:

Alter Table TableX Add Unique Index `UniqueRecord` (A,B,C,D)

问题是有时C可能为NULL。

我注意到了

`Insert IGNORE`

在某些情况下仍然会添加重复记录,结果是这些传入记录的C为NULL。

我通过以下方式测试了这个问题的假设:

Select concat(A,B,C,D) as Index from TableA where C is NULL

并且每个案例中的Index实际上都是NULL。从select:

中删除空字段后
Select concat(A,B,D) as Index from TableA where C is NULL

我得到了预期的字符串值vs nulls。

所以问题是,除了像set C='' where C is NULL之类的更新之外,是否有某种方法可以设置索引以使其有效?我不愿意简单地创建索引A,B,D,因为当C实际上不是NULL时,可能会引入不需要的欺骗。

更新: 我确实在创建索引时尝试使用IfNull但是Mysql不喜欢这样:

Alter Table TableA Add Unique Index UniqueLocator (A,B,IfNull(C,''),D

Mysql说:

[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'C,''),D)' at line 1

2 个答案:

答案 0 :(得分:0)

是MySQL允许在唯一索引中使用NULL,这是正确的做法。但是,如果你不喜欢,你可以将C列定义为NOT NULL。

答案 1 :(得分:0)

MySQL - 但不是所有数据库 - 允许唯一索引中的重复NULL值。我认为ANSI标准在这一点上是相当模糊的(或者甚至可能是矛盾的)。你基本上有两个选择。

第一种是为列定义默认值。这在代码方面可能不具吸引力,但它至少会在重复插入时产生错误。例如,如果“C”是对自动递增的id的外键引用,那么您可以使用-10作为默认值。如果是日期,您可以使用零日期。

另一个解决方案是触发器,您可以在执行插入(或更新)之前手动检查重复值。