MySQL与null值的比较

65
我在MySQL表中有一个名为CODE的列,可能为空。假设有一些行是CODE='C',我希望在选择结果集中忽略它们。我的结果集中可以包含CODE=NULL或CODE!='C'。
以下查询不会返回CODE为NULL的行:
SELECT * from TABLE where CODE!='C'

但是这个查询按预期工作,我知道这是正确的方法。

SELECT * from TABLE where CODE IS NULL OR CODE!='C'

我的问题是,为什么只有CODE!='C'的情况下,没有返回CODE=NULL的行?显然'C'不是NULL。我们在将无值与字符进行比较。有人能否解释一下为什么它不能这样工作?


可能是重复的问题:MySQL之谜:空值与非空字符串没有区别 - Marcus Adams
这个回答解决了你的问题吗?MySQL之谜:空值与非空字符串没有区别 - philipxy
7个回答

75

在MySQL中,NULL 被认为是“缺失的、未知的值”,而不是没有值。请参阅MySQL关于NULL的参考文献

NULL 进行任何算术比较都不会返回 true 或 false,而是返回 NULL。所以,NULL != 'C' 返回 NULL,而不是返回 true。

与“NULL”进行任何算术比较都将返回 false。要在SQL中检查这一点:

SELECT IF(NULL=123,'true','false') 

要检查 NULL 值,我们需要使用 IS NULLIS NOT NULL 运算符。


4
在所有关系型数据库中,null 是一个未知的缺失值,这与 MySQL 无关。 - Mike Ryan
3
在某些情况下,NULL 相当于 FALSE。这可能会使调试变得烦人,而修复似乎相当冗长和不可靠。考虑以下 SQL 语句:UPDATE table SET name=? WHERE id=id AND name<>?。显然,您的意思是如果更新会更改任何内容,则进行更新。但是,如果名称为 null,则永远不会更新该行。缺少数据并不等于某些实际值,因此它应该返回 true 并起作用。也许数据库需要一个“NULL 但为 TRUE”值类型,类似于 Perl 的“0 but true”。 - Jonathon
1
@JonathonWisnoski 不,你的例子并没有改变 NULL 的本质。你的例子提供了一种情况,即您希望将 NULL 与非相等值视为相同。在这种情况下,您可以使用 AND IFNULL(name, 'NOTMYVALUE')<>? -- 这是我的理解。ISNULL 函数在 MSSQL 中就是这样运作的,我相信 IFNULL 也是类似的。 - Sam DeHaan
1
在我看来,有意义的 NULL-safe 运算符应该基于概率: NULL<>?:一个未知值极有可能不等于其他值(包括 NULL),因此将其视为 TRUE 更有意义。它至少比假更接近真。NULL=?:一个未知值极有可能与其他值不相等,因此这里使用 TRUE 最为合适。 - Jonathon
1
MySQL 对待 NULLUNKNOWN 的方式并没有什么不同。在所有的 SQL 实现中(Postgres、SQL-Server、Oracle、DB2),当 WHERE 子句的结果为 UNKNOWN 时,行将从结果中丢弃(结果为 FALSE 的行也是如此)。 - ypercubeᵀᴹ
显示剩余3条评论

69
根据我的测试和这里的文档:http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html 您可以使用<= >来比较 null 并获得布尔结果
注意:它看起来像 NOT EQ 运算符,但实际上是 EQ 运算符。
例如:
select x <=> y; 
or
select @x <=> @y;

这也比较了字符串与null,字符串与字符串等。


4
如@Alan_Fullmer所述,"<=>"是等于运算符。如果您想检查不相等(<>),则只需在语句周围加上not。 例如:NOT(X <=> y)。 - JSS

20

在SQL中,NULL值是一种特殊的值,不可与其他任何值进行比较。与NULL直接比较的结果始终为NULL,尽管(不幸地)您可能会在某些实现中找到FALSE。

要测试空值,应使用IS NULLIS NOT NULL


通常被称为三态逻辑。 - sceaj
NULL与任何值进行比较,即使是自身,结果始终为NULL(在某些实现中为UNKNOWN),但从不为FALSE。你在哪里见过这种行为? - ypercubeᵀᴹ
@ypercube,我完全同意你的观点,但不幸的是这种情况确实存在。例如,请看这个问题的被接受答案:https://dev59.com/onI-5IYBdhLWcg3wc4Cw ,注意到了那个“not true”。 - cornuz
@comuz 那个回答只谈到了一个具体的系统(SQL Server)和一个具体的设置(ansi nulls off),这使得 SQL Server 处理空值的方式与 SQL 标准规定的方式不同。如果你是指这个,那就没问题。否则,在 SQL 中,Whatever = NULL 的结果是 UNKNOWN - ypercubeᵀᴹ
实际上,我的意思是一些实现/设置可能导致比较结果为FALSE/TRUE。 - cornuz

8
SELECT * 
FROM `table_name` 
WHERE IFNULL(`column_name` != 'C', TRUE)

3

我使用:

SELECT * from TABLE where NOT(CODE <=> 'C')

2
select * from user where application_id='1223333344' and name is null;

2
指定的问题也可能出现在连接操作中,上面的答案并不特别有帮助。我更喜欢的方法是通过合并到其他不可能的值来解决它。例如,这样做:
   select foo from bar
     inner join baz on bar.x = baz.y

如果 bar.xbaz.y 都为 null,则无法工作(连接不会带来结果)。解决方法是使用例如

   select foo from bar
     inner join baz on coalesce(bar.x, -1) = coalesce(baz.y, -1)

-1 是一个“不可能”值,意味着它永远不会出现在数据集中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接