2.NULL 的问题

摘要:
--返回nuknown值SELECT*FROMTEST1WHERE ID=NULL;SELECT*fromtest1hereidNULL;--返回正确的查询SELECT*FROMTEST1WHERE IDISNOTNULL;从测试1中选择*一致性为空;2.3.算术运算SELECT 10+NULL,10*NULL,10/NULLFROMDUAL--结果:nuknunknunknownSELECT‘A’| | NULL,CONCATFROMDUAL---结果是忽略NULL:Aa2.4.NULL相关函数2.4.1.NVL。用某个值替换NULL,但要替换的值的类型必须与其一致。selected,NVLFROMTEST1;2.4.2.NVL2.如果VALUE为空,则返回EXPR3。否则,返回EXPR2。EXPR2和EXPR3的类型是一致的。从dual中选择nulf(1,2);--结果:1SELECTNULIF(1,1)FROMDUAL——它在除法中是有用的。它可以代替DECODE和CASE。从dual中选择联合;--报告错误。类型不一致SELECTCOALESCEFROMDUAL--结果:12.4.5.CASEWHEN,DECODE进程NULL值。

/*************************************************
二、主题:NULL 的问题

*************************************************/
    CREATE TABLE TEST1
    (  
        ID   NUMBER(1) NOT NULL PRIMARY KEY,
        NAME VARCHAR(10)
    );
    CREATE unique INDEX IDX_TEST1 ON TEST1(NAME);
   
    INSERT INTO TEST1 VALUES(0,'0');
    INSERT INTO TEST1 VALUES(1,'1');
    INSERT INTO TEST1 VALUES(2,'2');
    INSERT INTO TEST1 VALUES(3,'A');
    INSERT INTO TEST1 VALUES(4,'B');
    INSERT INTO TEST1 VALUES(5,'a');  
    INSERT INTO TEST1(ID)  VALUES(7);  
   
=============================================================================
2.1.UNKNOWN 与 空格、0、其他不可见字符等不同

    SELECT DUMP(NULL) AS A,
           DUMP('') AS B,
           0 AS C
      FROM DUAL;--结果:NULL NULL 0
    --NULL 与空字符串,NULL是无类型或者说是任何类型的。
    SELECT CASE WHEN ''  = NULL THEN 1 ELSE 0 END AS COP1,  --引号内无内容,结果为:0
           CASE WHEN ' ' = NULL THEN 1 ELSE 0 END AS COP2  --引号内是空格,结果为:0
      FROM DUAL; 
     
2.2.任何与NULL的比较操作,都返回NULL。

    --返回nuknown 值  
    SELECT * FROM TEST1 WHERE ID=NULL;
    SELECT * FROM TEST1 WHERE ID<>NULL;
   
    --返回正确查询
    SELECT * FROM TEST1 WHERE ID IS NOT NULL;
    SELECT * FROM TEST1 WHERE NAME IS NULL;
   
2.3.算术运算
   
    SELECT 10+NULL,10*NULL,10/NULL FROM DUAL;    --结果:nuknown nuknown nuknown
    SELECT 'A'|| NULL,CONCAT(NULL,'a') FROM DUAL;--结果忽略NULL:A       a
   
2.4.NULL相关函数
 2.4.1. NVL(VALUE,REPLACEVALUE),替换NULL为某值,但是需要替换的值类型必须与之一致。
 
    SELECT ID , NVL(NAME,'NoValue') FROM TEST1;
   
 2.4.2. NVL2(VALUE,EXPR2,EXPR3),若VALUE为空,则返回EXPR3,否则返回EXPR2 ,EXPR2 与EXPR3的类型保持一致。
 
    SELECT ID,NVL2(NAME,1,'2') FROM TEST1; --若NAME字段不为空,则返回1,若为空则返回2,,此处返回的是NUMBER类型,因为1比'2' 的优先级高。
    SELECT ID,NVL2(NAME,1,NULL) FROM TEST1;--若NAME字段不为空,则返回1,否则返回null。
    SELECT ID,NVL2(NAME,NULL,'Y') FROM TEST1;--若NAME字段不为空,则返回NULL,否则返回'Y'.
   
 2.4.3. NULLIF(VALUE1,VALUE2),若VALUE1=VALUE2,则返回NULL,否则返回VALUE1,即继续用VALUE1;强制要求:两个值类型必须一致。
 
    SELECT NULLIF(1,2) FROM DUAL; --结果:1
    SELECT NULLIF(1,1) FROM DUAL;
          
    --在除法中的作用 ,比较有用,此处用法可以替代DECODE,CASE 。
    SELECT  10/0  FROM DUAL;  --错误,因为除数不能为0,小学生常识。
    SELECT 10/NULLIF(0,0) FROM DUAL;--结果为空值   
   
    SELECT ID,10/CASE WHEN ID = 0 THEN NULL ELSE ID END ID2 FROM TEST1;--正确,ID=0 的得到空值
    SELECT ID,10/DECODE(ID,0,NULL,ID) ID2 FROM TEST1; --正确,ID=0 的得到空值
    SELECT ID,10/NULLIF(ID,0) FROM TEST1;--正确,ID=0 的得到空值
 
    --实际用得不多
    SELECT NULLIF(NULL,1) FROM DUAL;--报错
    SELECT NULLIF(TO_CHAR(NULL),'1') FROM DUAL;--返回空值

    SELECT NULLIF(TO_NUMBER(NULL),1) FROM DUAL;   --报错
    SELECT NULLIF(TO_NUMBER(NULL,'9'),1) FROM DUAL;--返回空值  
 
 2.4.4. COALESCE (X1,X3,Xn...),从左往右取,得到第一个非空值,其中值类型必须一致,否则会报错。
   
    SELECT COALESCE(1,'1') FROM DUAL;--报错,类型不一致
   
    SELECT COALESCE(NULL,1,2) FROM DUAL;--结果:1
   
 2.4.5. CASE WHEN ,DECODE 处理 NULL值 。CASE 表达式得到数值型的,DECODE得到字符型的。
    --建立测试表TEST3
    =====================================================
    create table TEST3
    (
      sgnyear       NVARCHAR2(4) not null,
      areacode      NVARCHAR2(10) not null,
      transtypecode NVARCHAR2(10) not null,
      cargovolume   NUMBER(18,4),
      updateid      NUMBER(18),
      updatestate   NUMBER(1) default 0,
      updatetime    DATE default SYSDATE,
      businesstime  DATE default SYSDATE
    )  ;
    --插入数据,类似数据
    insert into TEST3 (SGNYEAR, AREACODE, TRANSTYPECODE, CARGOVOLUME, UPDATEID, UPDATESTATE, UPDATETIME, BUSINESSTIME)
    values ('2002', '360000', '5', 0.0000, 131715, 0, to_date('11-03-2014 10:54:08', 'dd-mm-yyyy hh24:mi:ss'), to_date('01-01-2002', 'dd-mm-yyyy'));

    insert into TEST3 (SGNYEAR, AREACODE, TRANSTYPECODE, CARGOVOLUME, UPDATEID, UPDATESTATE, UPDATETIME, BUSINESSTIME)
    values ('2002', '150000', '6', 37239.0000, 112343, 0, to_date('11-03-2014 10:54:08', 'dd-mm-yyyy hh24:mi:ss'), to_date('01-01-2002', 'dd-mm-yyyy'));

    insert into TEST3 (SGNYEAR, AREACODE, TRANSTYPECODE, CARGOVOLUME, UPDATEID, UPDATESTATE, UPDATETIME, BUSINESSTIME)
    values ('2011', '530000', '1', 60169.8590, 107295, 0, to_date('11-03-2014 10:54:08', 'dd-mm-yyyy hh24:mi:ss'), to_date('01-01-2011', 'dd-mm-yyyy'));

    insert into TEST3 (SGNYEAR, AREACODE, TRANSTYPECODE, CARGOVOLUME, UPDATEID, UPDATESTATE, UPDATETIME, BUSINESSTIME)
    values ('1995', '330000', '3', 1914.0000, 111791, 0, to_date('11-03-2014 10:54:08', 'dd-mm-yyyy hh24:mi:ss'), to_date('01-01-1995', 'dd-mm-yyyy'));

    insert into TEST3 (SGNYEAR, AREACODE, TRANSTYPECODE, CARGOVOLUME, UPDATEID, UPDATESTATE, UPDATETIME, BUSINESSTIME)
    values ('2008', '150000', '2', 38357.3386, 120727, 0, to_date('11-03-2014 10:54:08', 'dd-mm-yyyy hh24:mi:ss'), to_date('01-01-2008', 'dd-mm-yyyy'));
    .....
    =====================================================   
    --查询1.,根据年份分组,根据 TransTypeCode 为行列转换 标准,updatestate=2的数据视为无效数据
      select
             SgnYear,         
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '1',ROUND(CargoVolume,2),null) end) as Et01,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '2',ROUND(CargoVolume,2),null) end) as Et02,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '3',ROUND(CargoVolume,2),null) end) as Et03,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '4',ROUND(CargoVolume,2),null) end) as Et04,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '5',ROUND(CargoVolume,2),null) end) as Et05,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '6',ROUND(CargoVolume,2),null) end) as Et06,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '7',ROUND(CargoVolume,2),null) end) as Et07,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '8',ROUND(CargoVolume,2),null) end) as Et08,
             MAX(case when updatestate=2 then null else decode(TransTypeCode , '9',ROUND(CargoVolume,2),null) end) as Et09,
             case when min(updatestate)=2 then 2 else 1 end as updatestate         
         from TEST3
        group by SgnYear ;  
    --得到的结果,值全为数值型。

    --查询2.与查询1一样的思想,换一种方法
      select
             SgnYear,         
             MAX(decode(TransTypeCode , '1',decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2)))) as Et01,
             MAX(decode(TransTypeCode , '2',decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2)))) as Et02,
             MAX(decode(TransTypeCode , '3',decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2)))) as Et03,
             MAX(decode(TransTypeCode , '4',decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2)))) as Et04,                          
             case when min(updatestate)=2 then 2 else 1 end as updatestate         
         from TEST3
        group by SgnYear ;
     --查询2,得到的结果,值全部为 字符型

     --比较
     SELECT  decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2)),--得到的值为字符型
             decode(TransTypeCode , '1',decode(UPDATESTATE,2,NULL,ROUND(CargoVolume,2))),--得到的值为字符型
             case when updatestate=2 then null else CargoVolume end,--得到的值为数值型
             case when updatestate=2 then null else decode(TransTypeCode , '1',ROUND(CargoVolume,2),null) end--得到的值为数值s型
        FROM TEST3;

2.5.NULL与索引
    基本索引(B-TREE),是不存储全为NULL的列的。复合索引若有非NULL的列可以存储,但是全为空不存储。
    =================================================      
    CREATE TABLE TEST2
    (
     ID    NUMBER,
     VALUE NUMBER
    );
    CREATE INDEX IDX1_TEST2 ON TEST2(ID);--索引不会存储NULL值

    INSERT INTO TEST2 VALUES(6,1);
    INSERT INTO TEST2 VALUES(2,2);
    INSERT INTO TEST2 VALUES(3,1);
    INSERT INTO TEST2 VALUES(4,NULL);
    INSERT INTO TEST2 VALUES(1,NULL);
    =================================================
       
    SELECT * FROM TEST2 WHERE ID IS NOT NULL;--走索引
    SELECT * FROM TEST2 WHERE ID IS NULL;--不走索引。
   
    -- IS NULL 的查询若要走索引,可以建立一个有伪列的索引
   
    --建立有伪列的索引
    CREATE INDEX IDX2_TEST2  ON TEST2(ID,2);
   
    -------------更新表的统计信息,若不更新,还是与之前一样
    SQL>  EXEC   DBMS_STATS.GATHER_TABLE_STATS(USER,'TEST2',CASCADE=>TRUE) ;
 
    PL/SQL procedure successfully completed
    ---------------
   
    --再次查看执行计划
    SELECT * FROM TEST2 WHERE ID IS NOT NULL;--不走索引
    SELECT * FROM TEST2 WHERE ID IS NULL;    --走索引
   
    --此时,IS NOT NULL 的查询不走索引, IS NULL的查询走索引。 ^_^

2.6.建表时,NOT NULL 一定在DEFAULT 之后,不然会报错

2.7.NULL 与 排序
    --在ORDER BY 中 ,NULL 默认为最大值,所以ASC 时排在最后,DESC时排在最前面
    SELECT * FROM TEST1 ORDER BY NAME ASC;  --为NULL的排在后面
   
    SELECT * FROM TEST1 ORDER BY NAME DESC; --为NULL的排在前面
   
    --当然,可以显示制定NULL的排序规则
    SELECT * FROM TEST1 ORDER BY NAME ASC NULLS FIRST;--为NULL的排在前面
    SELECT * FROM TEST1 ORDER BY NAME DESC NULLS LAST;--为NULL的排在后面    
   
============================================================================= 

免责声明:文章转载自《2.NULL 的问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL升级方法一文件下载之断点续传(客户端与服务端的实现)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

layui select 下拉框 级联 动态赋值 与获取选中值

//下拉框必须在 里 不然监听事件没有作用 <div class="layui-form" > <div class="layui-inline"> <label class="layui-form-label">选择项目:</label>...

mongodb 操作 Date字段类型 mongodb shell api

一,环境 php 7.2 + thinkphp 5 mongodb 3.4 二,针对Date字段的操作 mongodb shell: 写入: db.students3.insert([ { "_id" : 1, "tests" : [ 95, 92, 90 ], "lastUpdate" : ISODate("2019-01-01T00:00:00Z")...

oracle hint

Hint概述基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担。但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比。 此时就需要DBA进行人为的干预,告诉优化器使用我们指定的存取路径或连接类型生成执行计划,从 而使语句高效的运行。例如,如果我们认为对于一个特定的语句,执行全表扫描要比执行索引扫描更...

MySQL日期数据类型、时间类型使用总结

MySQL 日期类型:日期格式、所占存储空间、日期范围 比较。 日期类型        存储空间       日期格式                 日期范围 ------------ ---------   --------------------- ----------------------------------------- datetime ...

decode用法

在查询数据,需要进行条件判断时,一般我们使用CASE...WHEN实现,当判断条件为相等时,除了使用CASE...WHEN实现,还可以使用DECODE函数。若要使用like、>、<等其他判断条件时,就只能使用CASE...WHEN实现了。 下面就解释下DECODE()函数的用法。 DECODE()使用方法:  decode(条件,值1,翻译值1...

MySQL之SQL优化详解(二)

目录 MySQL之SQL优化详解(二) 1. SQL的执行顺序 1.1 手写顺序 1.2 机读顺序 2. 七种join 3. 索引 3.1 索引初探 3.2 索引分类 3.3 建与不建 4. 性能分析Explain (1)id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序 (2) select_t...