问题 当其中一个字段为NULL时,MySQL错误地允许重复条目


使用InnoDB / MySQLi,我有一个简单的表: mytable。该表有四个字段: id (primary,auto_inc), field1field2field3。他们都是 BIGINT 而且,除了 id, 可 NULL

我添加了一个独特的约束,如下所示:

ALTER TABLE mytable ADD UNIQUE INDEX(field1,field2,field3);

但是,我完全能够添加以下行而不会生成任何错误。我希望这会产生“重复”错误,但它不会:

INSERT INTO mytable VALUES (NULL,3,NULL)
INSERT INTO mytable VALUES (NULL,3,NULL)

如果所有字段都具有非NULL值,它只会生成“重复”错误 - 例如,

INSERT INTO mytable VALUES (2,3,4)
INSERT INTO mytable VALUES (2,3,4)

即使一个(或多个)字段有错误,我如何告诉MySQL生成“重复”错误 NULL 值?

编辑: 这之前被添加为MySQL的“bug”: http://bugs.mysql.com/bug.php?id=25544


6333
2018-02-11 07:41


起源



答案:


你不能比较NULL(如果你用NULL比较任何东西,即使NULL = NULL,结果总是如此 FALSE)记录了这种行为 MySQL参考。

UNIQUE索引创建一个约束,以便索引中的所有值   必须是截然不同的如果您尝试使用a添加新行,则会发生错误   与现有行匹配的键值。对于所有引擎,一个独特的   index允许包含NULL的列的多个NULL值。

所以我认为唯一的方法是定义列NOT NULL或在触发器中处理此问题。


5
2018-02-11 07:59





问题的根源是 - 比较NULL-s。您应该理解NULL的逻辑含义。而且它“没有价值”。不 “零价值” 要么 “未知价值”但是 “没有价值”。这是一个很大的不同。

这就是为什么将唯一索引的一部分用于NULL的原因当然是个坏主意。您无法比较NULL,因为您无法比较两个值,两个值都不存在。因此,只要比较不能以正常方式适用于它们,DBMS就不能保持NULL-s是唯一的。是的,这样的事情 <=> 运算符存在于MySQL(或 IS NULL 在其他DBMS中) - 但这是关于如何处理与NULL值的比较的技术解决方案 - 但不是逻辑。

所以你在中间 XY-问题。不要将NULL-s与唯一键一起使用 - 它们不能定义什么是NULL以及什么是唯一键的意图。并从 技术观点 (参见关于索引创建的部分), NULL=NULL 将永远导致   - 因此,如果存在另一个NULL值,则允许插入NULL值。


3
2018-02-11 07:58





去: 如何在MySQL和其他数据库中使用唯一索引 并查看“MySQL NULLs”部分。


1
2018-02-11 07:53



如果这是正确的,那么答案是它无法完成 - 我只是不能在唯一索引中使用可以为NULL的字段并避免我遇到的问题。将来,您对该问题的贡献(即简单地提供链接)会更好地作为评论,而不是答案。 - a.real.human.being
MySQL在这种情况下处理NULL值,有些像空值,无法与其他值进行比较,因此不会抛出任何异常。我会提供评论而不是回答,但我是14分。一次的缩写;-D - Bartosz Polak
道歉,我忘了你需要一定的声誉级别来添加评论:) - a.real.human.being


答案:


你不能比较NULL(如果你用NULL比较任何东西,即使NULL = NULL,结果总是如此 FALSE)记录了这种行为 MySQL参考。

UNIQUE索引创建一个约束,以便索引中的所有值   必须是截然不同的如果您尝试使用a添加新行,则会发生错误   与现有行匹配的键值。对于所有引擎,一个独特的   index允许包含NULL的列的多个NULL值。

所以我认为唯一的方法是定义列NOT NULL或在触发器中处理此问题。


5
2018-02-11 07:59





问题的根源是 - 比较NULL-s。您应该理解NULL的逻辑含义。而且它“没有价值”。不 “零价值” 要么 “未知价值”但是 “没有价值”。这是一个很大的不同。

这就是为什么将唯一索引的一部分用于NULL的原因当然是个坏主意。您无法比较NULL,因为您无法比较两个值,两个值都不存在。因此,只要比较不能以正常方式适用于它们,DBMS就不能保持NULL-s是唯一的。是的,这样的事情 <=> 运算符存在于MySQL(或 IS NULL 在其他DBMS中) - 但这是关于如何处理与NULL值的比较的技术解决方案 - 但不是逻辑。

所以你在中间 XY-问题。不要将NULL-s与唯一键一起使用 - 它们不能定义什么是NULL以及什么是唯一键的意图。并从 技术观点 (参见关于索引创建的部分), NULL=NULL 将永远导致   - 因此,如果存在另一个NULL值,则允许插入NULL值。


3
2018-02-11 07:58





去: 如何在MySQL和其他数据库中使用唯一索引 并查看“MySQL NULLs”部分。


1
2018-02-11 07:53



如果这是正确的,那么答案是它无法完成 - 我只是不能在唯一索引中使用可以为NULL的字段并避免我遇到的问题。将来,您对该问题的贡献(即简单地提供链接)会更好地作为评论,而不是答案。 - a.real.human.being
MySQL在这种情况下处理NULL值,有些像空值,无法与其他值进行比较,因此不会抛出任何异常。我会提供评论而不是回答,但我是14分。一次的缩写;-D - Bartosz Polak
道歉,我忘了你需要一定的声誉级别来添加评论:) - a.real.human.being