簡體   English   中英

MySQL之謎:空值與非空字符串沒有區別

[英]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 NULLIS 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM