
SQL 中的 NULL
(譯自 NULL Values in SQL Queries)
SQL 中的 NULL 到底是怎樣一個(gè)概念呢?有什么要注意的嗎?這篇文章就是要把它講清楚。
查詢(xún)某列值為 NULL 的數(shù)據(jù)
當(dāng)想查詢(xún)某一列值為 NULL 的數(shù)據(jù)時(shí),下面兩種哪個(gè)更好呢?
SELECT * FROM SOME_TABLE
WHERE SOME_COLUMN=NULL
還是
SELECT * FROM SOME_TABLE
WHERE SOME_COLUMNISNULL
答案是,第二種更好。
為什么呢?為什么其他的比較都不用 IS 呢?比如想知道一個(gè)字段值是不是等于1,可以用一個(gè)簡(jiǎn)單的 WHERE 子句:
WHERE SOME_COLUMN = 1
所以到底為什么對(duì) NULL 區(qū)別對(duì)待使用 IS 呢?
因?yàn)椋?strong>在 SQL 中,NULL 表示「未知」的意思,就是「未知」,不知道,不了解,未知?。ㄔ模簎nknown)
NULL 是「未知」
在大多數(shù)數(shù)據(jù)庫(kù)中,NULL 和空字符串是有區(qū)別的。
但也有例外,比如在 Oracle 中,根本就不允許一個(gè)值是空字符串,Oracle 中所有的空字符串都會(huì)自動(dòng)轉(zhuǎn)換成 NULL。
不過(guò)對(duì)于其他大多數(shù)數(shù)據(jù)庫(kù)來(lái)說(shuō),NULL 和空字符串是區(qū)別對(duì)待的:
- 空字符串也是一種值,只不過(guò)是空的而已。
- NULL 是一個(gè)「未知」值。(或者說(shuō)是「未知」,沒(méi)有「值」的概念)
舉個(gè)例子,就好像問(wèn):美國(guó)總統(tǒng)西奧多·羅斯福的中間名是什么?
- 一種回答可能是:我不知道西奧多·羅斯福的中間名是什么。(這種情況「中間名」字段就應(yīng)該是 NULL)
- 還有一種回答可能是:西奧多·羅斯福沒(méi)有中間名,他父母沒(méi)給他起中間名,我知道的事實(shí)就是西奧多·羅斯福沒(méi)有中間名。(這種情況「中間名」就應(yīng)該為空字符串)
謹(jǐn)記 NULL 就是「未知」這個(gè)概念,就可以很容易處理一些使用 NULL 時(shí)可能遇到的麻煩。
比如下面的 WHERE 子句就會(huì)得到 true,那就能查到數(shù)據(jù)(如果數(shù)據(jù)庫(kù)有數(shù)據(jù)的話):
SELECT * FROM SOME_TABLE
WHERE 1 = 1
下面的子句會(huì)得到 false,永遠(yuǎn)都查不到數(shù)據(jù):
SELECT * FROM SOME_TABLE
WHERE 1 = 0
而下面的 WHERE 子句會(huì)得到 NULL,因?yàn)閿?shù)據(jù)庫(kù)并不知道 1 和 NULL(「未知」)是什么關(guān)系,他們相等不相等,數(shù)據(jù)庫(kù)不清楚,所以 WHERE 子句得到的又是 NULL(「未知」)。所以下面的查詢(xún)永遠(yuǎn)也不會(huì)返回任何數(shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE 1 = NULL
三元邏輯(原文為 Ternary Logic)
一個(gè) SQL 語(yǔ)句中 WHERE 子句有三種不同的結(jié)果
- true(會(huì)返回?cái)?shù)據(jù))
- false(不會(huì)返回?cái)?shù)據(jù))
- NULL(「未知」也不會(huì)返回?cái)?shù)據(jù))
好了,那既然 false 和 NULL 都不會(huì)返回?cái)?shù)據(jù),那干嘛還要關(guān)注它們的區(qū)別呢?
當(dāng)遇上 NOT() 的時(shí)候就有問(wèn)題了。
比如下面這個(gè)語(yǔ)句,1 肯定等于 1,顯然經(jīng)過(guò) NOT() 后就會(huì)變成 false,那就永遠(yuǎn)不會(huì)返回?cái)?shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE NOT(1 = 1)
下面這句呢,顯然 NOT() 后會(huì)得到 true,當(dāng)然會(huì)返回?cái)?shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE NOT(1 = 0)
但是這句呢?
SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)
上面這句 1 = NULL 由于數(shù)據(jù)庫(kù)不知道 NULL 是什么,「未知」,所以其結(jié)果是 NULL。對(duì) NOT() 來(lái)說(shuō)呢,它也不知道 NULL 是什么,該怎么處理,所以也會(huì)返回 NULL,所以 WHERE 子句得到的是 NULL,既不是 true 也不是 false 而是 NULL,所以上面這條語(yǔ)句永遠(yuǎn)都不會(huì)返回?cái)?shù)據(jù)。
那么好了,看下面這兩條語(yǔ)句,雖然是相反的條件,但結(jié)果一致:都不會(huì)查詢(xún)到數(shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)
SELECT * FROM SOME_TABLE
WHERE 1 = NULL
NOT IN 和 NULL
NOT IN 也是非常值得注意的。
比如下面這個(gè) SQL,1 顯然在后面的列表中,WHERE 就會(huì)得到 true,那么就會(huì)查詢(xún)到數(shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE 1 IN (1, 2, 3, 4, NULL)
再看下面這句,顯然 1 是在數(shù)組中的,那么 NOT IN 就會(huì)得到 false,那么就不能查詢(xún)到數(shù)據(jù)。
SELECT * FROM SOME_TABLE
WHERE 1 NOT IN (1, 2, 3, 4, NULL)
再看這個(gè):
SELECT * FROM SOME_TABLE
WHERE 5 NOT IN (1, 2, 3, 4, NULL)
先說(shuō)答案:這句語(yǔ)句不能查詢(xún)到數(shù)據(jù)。
5 在不在后面的列表中呢?數(shù)據(jù)庫(kù)是不知道的,因?yàn)槔锩嬗袀€(gè) NULL,誰(shuí)知道 5 等不等于 NULL(「未知」),不知道,所以 5 NOT IN (1, 2, 3, 4, NULL) 得到的是 NULL,所以查詢(xún)不到數(shù)據(jù)。
小結(jié)
以上,NULL 就是 NULL,是「未知」,這樣一種概念的重要性就介紹完了。理解這一點(diǎn),在構(gòu)建復(fù)雜 SQL 時(shí)將很有用。