MySQL之谜:空值与非空字符串没有区别

时间:2010-08-04 10:49:30

标签: mysql null

为什么此查询返回0行?

select t.f1, t.f2
from (select null f1, 'a' f2 from dual) t
where t.f1<>t.f2;

这是我所拥有的复杂查询的简化版本。我想比较两个包含一对一相关数据的表,并且我想选择那些包含某些字段的不同值的行。但也可能存在其中一个表中缺少一行的情况。 LEFT JOIN正确地返回这些行的空值,但是,WHERE子句错误地(或意外地)过滤掉这些行。

为什么 - 在这种情况下 - 'null'与任何非空值(如'a')不同?

让我疯狂的是这个

select t.f1, t.f2
from (select null f1, 'a' f2 from dual) t;

返回1行(正如我所料)但是这个

select t.f1, t.f2
from (select null f1, 'a' f2 from dual) t
where t.f1=t.f2;

返回0行!! 所以null不等于'a',null与'a'没有区别!!

请......有人可以解释一下吗?

5 个答案:

答案 0 :(得分:5)

完全。 NULL表示未知值,不是任何特定值(它与C中的NULL不同,或者Ruby中的nil等等。)在SQL中,如果将某些内容与未知值,结果也是未知数。而且你不会得到WHERE条件未知的行。

试试这个:

SELECT NULL <> 2;

您将看到NULL作为结果。

试试这个:

SELECT * FROM t WHERE NULL;

并且即使表t很大,也不会出现任何行。

如果你真的需要你所说的你想要的东西(我不是在鼓吹这个),你可以这样做:

SELECT T.f1, T.f2
FROM (SELECT NULL f1, 'a' f2) T
WHERE ((T.f1 IS NULL OR T.f2 IS NULL)
    AND (T.f1 IS NOT NULL OR T.f2 IS NOT NULL))
    OR T.f1 <> T.f2

答案 1 :(得分:3)

NULL的概念是SQL新手的常见混淆源,他们常常认为NULL被视为其他值。

事实并非如此。从概念上讲,NULL意味着“缺失的未知值”,因此它的处理方式截然不同。

你所看到的很容易解释。请考虑以下示例:

CREATE TABLE mytb (id int, value int);

INSERT INTO mytb VALUES (1, 100);
INSERT INTO mytb VALUES (2, 200);
INSERT INTO mytb VALUES (3, NULL);
INSERT INTO mytb VALUES (4, 400);

以上意味着对于id = 3行,该值为“未知”。它可以是300,也可以是100或其他任何内容。

因此,当您请求以下内容时:

SELECT * FROM mytb WHERE value <> 100;
+------+-------+
| id   | value |
+------+-------+
|    2 |   200 |
|    4 |   400 |
+------+-------+
2 rows in set (0.00 sec)

不会返回id = 3行,因为NULL <> 100会返回“unknown”。我们不知道行id = 3的值是否为100,因此表达式不会返回true。我也没有回复false。它返回“unknown”(NULL)。

只有当表达式为WHERE时,才能满足true子句的条件。当您将某些内容与NULL进行比较时,表达式永远不会成立。它将是“未知的”。

答案 2 :(得分:1)

SQL NULL无法按照您希望的方式工作:http://en.wikipedia.org/wiki/Sql_null

简而言之,NULL = NULL不是真的。 NULL <> NULL不是真的。 NULL <> 1不是真的。等等。

答案 3 :(得分:0)

尝试执行此查询:

   select * from dual where NULL = NULL

返回0行。这是因为要将值与null进行比较,您必须执行IS NULLIS NOT NULL,否则它将返回 false

答案 4 :(得分:0)

NULL值没什么,它不能等于或不等于某事。 如果要检查值是否为null - 请使用“IS NULL”语句:

select t.f1, t.f2
from (select null f1, 'a' f2 from dual) t
where t.f1 IS NULL

如果你想检查你的值是否相等 - 你可以在可空列上使用COALESCE函数:

select t.f1, t.f2
from (select null f1, 'a' f2 from dual) t
where COALESCE(t.f1, '')<>COALESCE(t.f2, '');