假设有一张表格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。