[英]MySQL mystery: Null value is not different from non-null string
為什么此查詢返回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'不同!!
請...有人可以解釋一下嗎?
究竟。 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
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
的行,該值為“unknown”。 它可能是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”。 我們不知道row id = 3
的值是否為100,因此表達式不返回true
。 我也沒有回復false
。 它返回“unknown”( NULL
)。
只有表達式為true
時才能滿足WHERE
子句的條件。 將某些內容與NULL
進行比較時,表達式永遠不會成立。 它將是“未知的”。
SQL NULL不能按照您希望的方式工作: http : //en.wikipedia.org/wiki/Sql_null
簡而言之, NULL = NULL
不正確。 NULL <> NULL
不成立。 NULL <> 1
不成立。 等等。
嘗試執行此查詢:
select * from dual where NULL = NULL
它返回0行。 這是因為要將值與null進行比較,您必須執行IS NULL
或IS NOT NULL
,否則它將返回false 。
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, '');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.