为什么此查询返回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'没有区别!!
请......有人可以解释一下吗?
答案 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 NULL
或IS 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, '');