SQL中的null

对Oracle SQL中的null小结如下:

1.1       null

? null 值计算的结果仍是null

? null 是一个未分配的、未知的,或不适用的值

? null不是0,也不是空格

1.1.1       null值的运算

null参数的算术表达式的结果仍然为null

SQL>  select ‘*‘||1/null||‘*‘ res1,‘*‘||1*null||‘*‘ res2, ‘*‘||(1-null)||‘*‘ res3 from dual;

RE RE RE

-- -- --

** ** **

SQL>select null/0 from dual;

NULL/0

----------

SQL>select 1/0 from dual;

select1/0 from dual

*

ERROR atline 1:

ORA-01476:divisor is equal to zero

取模

SQL>select  ‘*‘||mod(9,null)||‘*‘ res fromdual;

RE

--

**

从NULL/0没有报错的情况,我们可以推测出,Oracle发现算术表达式中有null时,并没有真正地计算该表达式,而是直接返回了null。

SQL>select 1 from dual where null!=null;

no rowsselected

SQL>select 1 from dual where null = null;

no rowsselected

SQL>select 1 from dual;

1

----------

1

不管是null!=null 还是null=null计算的结果都为false(实际上是返回了null, null在逻辑中表现为false),可见不管是算术运算还是逻辑运行,只要null参与,结果就是null

1.1.2       null值与字符串连接

null与字符型字段连接时,表现为什么都没有"",相当于零个字符

SQL>select ‘*‘||null||‘*‘ from dual;

‘*

--

**

注意: 这里涉及到了中文的显示,如果出现乱码,请确认数据库服务nls_database_parameters,服务器echo $NLS_LANG/ set NLS_LANG,以及客户端v$nls_parameters的编码设置是否一致。

1.1.3       null的查询方式

SQL> select * from emp where comm is null;

其他的查询方式会先过滤过列的null值,即null不参与is null /is not null之外的查询

SQL>select count(*) from emp;

COUNT(*)

----------

14

SQL>select count(*) from emp where comm<=500;

COUNT(*)

----------

3

SQL>select count(*) from emp where comm>500;

COUNT(*)

----------

1

1.1.4       null所在列的排序

在order by 排序中,null值最大

SQL>select ename, comm from emp order by comm;

TURNER                                    0

ALLEN                      300

WARD                      500

MARTIN                                1400

SCOTT

KING

ADAMS

JAMES

FORD

MILLER

BLAKE

JONES

SMITH

CLARK

14 rowsselected.

1.1.5       is null不走索引

在SQL的优化中有时会遇到SQL语句有索引也应该走索引,但最终却没有走索引的情况,这里的is null就是其中的一种情况。

create table n1(sid integer,sname varchar2(120));

插入1W条记录,第1W条的sname值为null

begin

for i
in 1..9999 loop

insert
into n1 values(i,‘name‘||i);

if mod(i,100)=0then

commit;

end
if;

end loop;

insert
into n1(sid)values(10000);

commit;

end;

查询sname列值走的是索引范围扫描

SQL> explain plan for select * from n1 where sname = 'name1';
Explained.

SQL> select * from table(dbms_xplan.display);
Plan hash value: 3644017351
--------------------------------------------------------------------------------
| Id  | Operation	 | Name 	| Rows	| Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |		|     1 |    75 |     2   (0)| 00:00:01
|
|*  1 |  INDEX RANGE SCAN| N1_SNAME_IND |     1 |    75 |     2   (0)| 00:00:01
|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("SNAME"='name1')
Note
-----
   - dynamic sampling used for this statement (level=2)

is null方式查询,虽然sname中为null的记录1W行中只有一行,但还是没有走索引,也就是说is null不走索引。

SQL> explain plan for select * from n1 where sname is null;
Explained.

SQL> select * from table(dbms_xplan.display);
Plan hash value: 2416923229
--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |     1 |    75 |     9   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| N1	 |     1 |    75 |     9   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("SNAME" IS NULL)
Note
-----
   - dynamic sampling used for this statement (level=2)
17 rows selected.

如果实际情况确实需要is null查询走索引呢?可通过创建联合索引的方式来实现。

drop index n1_sname ;

create index n1_sname_ind on n1(sname,sid);

SQL> explain plan for select * from n1 where  sid is not null and sname is null ;

SQL> select * from table(dbms_xplan.display);
Plan hash value: 3644017351
-------------------------------------------------------------------------------
| Id  | Operation	 | Name 	| Rows	| Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |		|     1 |    75 |     3   (0)| 00:00:01
|
|*  1 |  INDEX RANGE SCAN| N1_SNAME_IND |     1 |    75 |     3   (0)| 00:00:01
|
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("SNAME" IS NULL)
       filter("SID" IS NOT NULL)
Note
-----
   - dynamic sampling used for this statement (level=2)

18 rows selected.

可以看到创建联合索引后,SQL查询所耗费的资源明显降低。

需要注意的是我们查询最频繁最经常使用列,比如sname要放在联合索引的第一列;同时要走联合索引,需要where后面的条件出现联合索引包含的所有的字段,这也是为什么加了sid这个字段的原因。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 23:32:42

SQL中的null的相关文章

SQL中的Null深入研究分析

虽然熟练掌握SQL的人对于Null不会有什么疑问,但总结得很全的文章还是很难找,看到一篇英文版的, 感觉还不错. Tony Hoare 在1965年发明了 null 引用, 并认为这是他犯下的"几十亿美元的错误". 即便是50年后的今天, SQL中的 null 值还是导致许多常见错误的罪魁祸首. 我们一起来看那些最令人震惊的情况. Null不支持大小/相等判断 下面的2个查询,不管表 users 中有多少条记录,返回的记录都是0行: select * from users where

深入详解SQL中的Null

NULL 在计算机和编程世界中表示的是未知,不确定.虽然中文翻译为 "空", 但此空(null)非彼空(empty). Null表示的是一种未知状态,未来状态,比如小明兜里有多少钱我不清楚,但也不能肯定为0,这时在计算机中就使用Null来表示未知和不确定. 虽然熟练掌握SQL的人对于Null不会有什么疑问,但总结得很全的文章还是很难找,看到一篇英文版的, 感觉还不错. Tony Hoare 在1965年发明了 null 引用, 并认为这是他犯下的"几十亿美元的错误"

SQL中的NULL值

除is [not] null之外,空值不满足任何查找条件.–如果null参与算术运算,则该算术表达式的值为null.–如果null参与比较运算,则结果可视为false.在SQL-92中可看成unknown.–如果null参与聚集运算,则除count(*)之外其它聚集函数都忽略null.   例:select    sum(SAL)           from     PROF   例:select    count(*)           from     PROF– 详细分析 SQL中的N

深入具体解释SQL中的Null

NULL 在计算机和编程世界中表示的是未知,不确定.尽管中文翻译为 "空", 但此空(null)非彼空(empty). Null表示的是一种未知状态.未来状态,比方小明兜里有多少钱我不清楚,但也不能肯定为0,这时在计算机中就使用Null来表示未知和不确定. 尽管熟练掌握SQL的人对于Null不会有什么疑问,但总结得非常全的文章还是非常难找,看到一篇英文版的, 感觉还不错. Tony Hoare 在1965年发明了 null 引用, 并觉得这是他犯下的"几十亿美元的错误&quo

SQL 中【NULL】和【无】烦躁的问题

很烦躁,烦躁的很,总结一下. 先简单的说下: NULL   : 不确定的东西 无       :没有东西 复杂的见下文....... 一 .null值 下面举个最简单的例子,平常工作当中肯定比这个sql复杂的多,在这只是把这个易错点呈现出来,他可能是一个复杂sql出错的小的 不容易被发现的一个问题. 上面是一个很简单表的所有数据.area_num 区域编码 area_name 区域名称 delflag 有无效标识 1有效 0无效(其中淮北 和宣城的delflag为null). 现在想找出有效的那

sql 中的NULL小问题 ,大bug

今天在写退款的的SQL的时候遇到一个问题,直接导致之前记录的所有操作日志,清空了,还好自己有看数据的习惯,下面贴上代码 1 UPDATE TradeUser 2 SET 3 UserScore=@UserScore 4 Remark=ISNULL(Remark,'')+' '+@UserName +' 手动取消付款,退还积分' 5 WHERE UserId=@UserID 执行这句SQL后,备注直接清空,百思不得其解,找不到原因.其实原因很简单,传入的@UserName是NULL,导致字符串和N

SQL 语句中关于 NULL 的那些坑

问题描述 今天在跟进公司内部测试平台线上问题的时候,发现一个忽略已久的问题. 为了简化问题描述,将其进行了抽象. 有一张数据表qms_branch,里面包含了一批形式如下所示的数据: id name types 1 dashboard_trunk dashboard 2 monkey_trunk monkey 3 dashboard_projects_10_9_9 dashboard 4 performance_trunk   5 performance_projects_10_9_8 perf

SQL中IS NOT NULL与!=NULL的区别

平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS NOT NULL去做条件判断,因为SQL默认情况下对WHERE XX!= Null的判断会永远返回0行,却不会提示语法错误. 这是为什么呢? SQL Server文档中对Null值的比较运算定义了两种规则,如在SQL Server 2000中: 规则一是是ANSISQL(SQL-92)规定的Null

SQL中空值与NULL区别

很多人都有过这样的问题吧   在SQL中填充空值与NULL有什么区别 现在我以一个实例给大家分享一下自己的想法  恳请大家给予批评也指正 谢谢 创建一个监时表 CREATE TABLE #temp ( name VARCHAR(50) ) 填充三条资料 如下: INSERT INTO #tempVALUES ( NULL )INSERT INTO #tempVALUES ( 'Tom' )INSERT INTO #tempVALUES ( '' ) 使用如下语法查询 SELECT COUNT(n