假設有一張表格table1
col_a |
col_b |
(空格) |
1 |
|
2 |
|
3 |
|
|
a |
查詢:
select * from table1 where col_a = '' --0條記錄
select * from table1 where col_a is null --3條記錄
select * from table1 where col_a !='a' --1條記錄
解釋:null的意義:沒有值,不等價於任何值,是一個未知數,當null作為條件進行操作時,就不能用"="(雖然語法沒有錯),即不能定值判斷,應該使用is null 或者 is not null
除is null/ is not null語句外,對null的操作均不會出現返回在結果中
插入:
插入空字符串的時候會自動轉化為null,在Oracle中沒有空字符串,只有null,例如:
insert into table1 values(null, null); -- 插入NULL,插入成功
insert into table1 values('a', ''); -- 第二個字段類型為int型,但還是能插入成功,再次證明,’’ 被當作了null處理,如果是字符串,執行會報錯
函數:
在使用AVG,MAX,SUM,COUNT等函數時,為NULL的紀錄往往會被忽略。
例如:
select AVG(col_b) from table1; -- 結果為 2 ,NULL的紀錄行忽略掉了
select MAX(col_b) from table1; -- 結果為 3
select SUM(col_b) from table1; -- 結果為 6
select COUNT(col_b) from table1; -- 結果為 3
select COUNT(col_a) from table1; -- 結果為 2
select COUNT(*) from table1; -- 結果為 5
排序:
select * from table1 order by address -- null值會排在后面
select * from table1 order by address desc -- null值會排在前面
Order by排序時缺省認為null是最大值,ASC升序則被排在最后,而DESC降序則排在最前
解決:如果要改變排序方式,可以:
1. 使用 nvl 函數,例如在排序中使用ORDER BY NVL(FIELD, '0')
2. 使用其它函數,例如:decode,case
3. nulls first或nulls last(注:Nulls first:表示null值的記錄將排在最前;Nulls last:表示null值的記錄將排在最后),例:
select * from table1 order by aac001 asc nulls first --null值始終放在最前面
select * from table1 order by aac001 desc nulls last --null值始終放在最后面
計算:
對NULL的=、!=、>、<、>=、<=等操作的結果都為NULL。
對NULL進行+、-、*、/等操作的結果也都為NULL。
其他:
AND操作:
AND |
TRUE |
FALSE |
NULL |
TRUE |
TRUE |
FALSE |
NULL |
FALSE |
FALSE |
FALSE |
FALSE |
NULL |
NULL |
FALSE |
NULL |
OR操作:
OR |
TRUE |
FALSE |
NULL |
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
TRUE |
FALSE |
NULL |
NULL |
TRUE |
NULL |
NULL |
NOT操作:
NOT TRUE |
NOT FALSE |
NOT NULL |
FALSE |
TRUE |
NULL |
解釋:NULL是未知的,但目前NULL的類型為布爾類型,因此NULL只有可能是TRUE或者FALSE中的一個。所以,這邊可以把NULL看成是(TRUE OR FALSE)
NULL的深入分析:
(參考:https://blog.csdn.net/lotusyangjun/article/details/6177169)
一、NULL是數據庫中特有的數據類型,當一條記錄的某列為NULL,則表示該列的值是未知的、是不確定的。既然是未知的,就有無數種的可能性。因此,NULL並不是一個確定的值。
判斷一個字段是否為NULL,應該用IS NULL或IS NOT NULL,而不能用‘=’。對NULL的判斷只能定性,即是不是NULL(IS NULL/IS NOT NULL),而不能定值。簡單的說,由於NULL存在着無數的可能,因此兩個NULL不是相等的關系,同樣也不能說兩個NULL就不相等,或者比較兩個NULL的大小,這些操作都是沒有意義,得不到一個確切的答案的。因此,對NULL的=、!=、>、<、>=、<=等操作的結果 都是未知的,也就算說,這些操作的結果仍然是NULL。
同理,對NULL進行+、-、*、/等操作的結果也是未知的,所以也是NULL。
所以,很多時候會這樣總結NULL,除了IS NULL、IS NOT NULL以外,對NULL的任何操作的結果還是NULL。
由於引入了NULL,在處理邏輯過程中一定要考慮NULL的情況。同樣的,數據庫中的布爾值的處理,也是需要考慮NULL的情況,這使得布爾值從原來的TRUE、FALSE兩個值變成了TRUE、FALSE和NULL三個值:
TRUE AND NULL:NULL
TRUE OR NULL:TRUE
FALSE AND NULL:FALSE
FALSE OR NULL:NULL
NULL AND TRUE:NULL
NULL OR TRUE:TRUE
NULL AND FALSE:FALSE
NULL OR FALSE:NULL
NULL AND NULL:NULL
NULL OR NULL:NULL
NOT TRUE:FALSE
NOT FALSE:TRUE
NOT NULL:NULL
注:NULL是未知的,但是目前NULL的類型是布爾類型,因此NULL只有可能是TRUE或者FALSE中的一個。所以,這邊可以把NULL看成是(TRUE OR FALSE)。
如果只是給出一個NULL,那么它是可以代表任意的類型的。
二、以上面的表為例:
select * from table1 where col_a in ('a',' ',null);
查詢結果為2條,col_a in ('a',' ',null); 等價於col_a ='a' or col_a = ' ' or col_a = null,當查到第一條時,等價於false or true or null,所以總的查詢結果為2條。
select * from table1 where col_a not in ('a',' ',null);
查詢結果為0條,col_a not in ('a',' ',null); 等價於col_a !='a' and col_a != ' ' and col_a != null,當查到第一條時,等價於true and false and null,結果為false,所以總的查詢結果為0條。
三、空字符串差不多就是和null等價
例如:SELECT 1 FROM DUAL WHERE '' = '' --查詢結果為空
SELECT 1 FROM DUAL WHERE '' IS NULL; --結果為1
SELECT DUMP(''), DUMP(NULL) FROM DUAL; --結果為null null
SELECT NULL || 'A', 'B' || NULL, NULL || NULL FROM DUAL; --結果為A B null
從NULL的存儲格式上解釋。Oracle在存儲數據時,先是存儲這一列的長度,然后存儲列數據本身。而對於NULL,只包含一個FF,沒有數據部分。簡單的說,Oracle用長度FF來表示NULL。
由於Oracle在處理的數據存儲的時候盡量避免0的出現,因此,認為這里FF表示的是長度為0也是有一定道理的。或者從另一方面考慮,NULL只有一個長度,而沒有數據部分。
而對於字符串來說,不管是長度為0的字符串還是沒有任何數據的字符串,所代表的含義都是一個空字符串。從這一點上講,空字符串就是NULL也是有一定的道理的。
如果認為空字符串是字符形式的NULL,那么||操作的結果就不難理解了。
最后需要說明的是,不要將ORACLE里面的空字符串’’與C里面的空字符串””混淆。C里面的空字符串並非不不含任何數據,里面還包含了一個字符串結束符。C語言中的空字符串””對應Oracle中ASCII表中的0值,既CHR(0)。但CHR(0)是一個確定的值,它顯然不是NULL。