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的排在后面    
   
=============================================================================

NULL 的问题

时间: 2025-01-06 11:05:42

NULL 的问题的相关文章

Spring rabbitMq 中 correlationId或CorrelationIdString 消费者获取为null的问题

问题 在用Spring boot 的 spring-boot-starter-amqp   快速启动 rabbitMq 是遇到了个坑 消费者端获取不到:correlationId或CorrelationIdString 问题产生的原因 correlationId 的在 spring rabbitmq 2.0 以后 byte方式会被放弃,所以 目前 代码中有些地方没有改过来,应该算一个BUG @SuppressWarnings("deprecation") public class De

值不能为null.参数名: viewInfo,如何解决

有蓝队网络服务器租用客户反映在一台服务器上使用数据库管理工具时弹出了如下错误 :值不能为null.参数名: viewInfo (Microsoft.SqlServer.Management.SqlStudio.Explorer 错误信息如上图: 解决方法:点击确定 登陆上去.查看---已注册的服务弹出报错信息,点详细. 会找到一个类似无法读取C:\Users\www.landui.com\AppData\Local\Temp\3\xx.tmp 的报错信息. 打开对应目录C:\Users\www.

java 的&quot;&quot;和null的区别

null和""的区别 问题一: null和""的区别 String s=null; string.trim()就会抛出为空的exception String s=""; string.trim()就不会抛,为什么? 答: NULL代表声明了一个空对象,根本就不是一个字符串. ""代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串. NULL代表声明了一个空对象,对空对象做任何操作都不行的,除了=和== "

shell输出的那个垃圾桶——/dev/null

昨晚花费一整晚在知乎回答了一个关于shell里面的重定向输出到/dev/null的问题.果断今晚也同步发在这里,反正也没人看~~~~ 以下来自一个重度linux使用患者不请自来的回答. 先用简单的语言回答题主的问题: shell程序中 2> /dev/null 代表什么意思? 答:"2> /dev/null" 代表忽略掉错误提示信息. 如题 2> 代表什么意思?讲错误输出删除? 答:"2>" 代表重定向操作错误提示信息.只有这两个字符并不能删

sendUserActionEvent() mView== null after clicking on button

this is not a problem related to your code, but related to S4 android version. Same question has been posed on stackoverflow : sendUserActionEvent() is null So, just ignore it

2&gt;&1 &gt;/dev/null & 与/dev/null 2&gt;&1含义

/dev/null 代表空设备文件 > 代表重定向到哪里,例如:echo "123" > /home/123.txt 1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null" 2 表示stderr标准错误 & 表示等同于的意思,2>&1,表示2的输出重定向等同于1 1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到

PHP如何区分未定义,null

今天遇到群里一个人提的问题,isset无法区分未定义和null怎么办? 下面是代码. <?php$b = null;$c = '';$arr = get_defined_vars(); if(!isset($a) && !array_key_exists('a', $arr)){    echo '变量未定义';}else if($a === null){    echo '变量已定义,但变量为空';}else{    echo '变量已定义且变量不为空';} echo '<b

前端面试准备2----Javascript中的Undefined和null小结

JavaScript中有两个表示“空”的值,分别是Undefined和null: (1)Undefined 定义了一个全局变量,它的值是 undefined,这个变量也被称为undefined. 但是这个变量不是一个常量,也不是一个关键字.这意味着它的值可以轻易被覆盖. ES5 提示: 在 ECMAScript 5 的严格模式下,undefined 不再是可写的了. 但是它的名称仍然可以被隐藏,比如定义一个函数名为 undefined. 下面的情况会返回 undefined 值: 访问未修改的全

在Java代码中避免 &quot;!=null &quot; 判断

这对于我来说是一个很合理常见的问题,由初级过度到中级程序员的时候经常会遇到.他们不知道也不信任正在用的约定,并且小心的检查着null.还有当他们写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调用者去检查Null. 换种方式来说,有两种情景空指针的检查会出现: 就约定来说是一个合理的响应 不是合理的响应 第二种很简单,可以通过用assert或者直接允许失败,例如NullPointerException.Assertions是一个从Java1.4加进来的高度未被利用的特性,

鼠标键盘无法进入:(EE) config/hal: couldn’t initialise context: (null)

vi /var/log/Xorg.0.log 发现有一行:(EE) config/hal: couldn’t initialise context: (null) 在xorg.conf里面加上下面选项,问题解决: Section "ServerFlags" Option   "AllowEmptyInput"     "false" Option   "AutoAddDevices"      "false"