oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)

最近,在做开发、写存过的时候碰到一些问题,找了好长时间才发现原因,而且是以前不知道的。所以在这给记下来 给自己备忘和大家参考。

一 、null值

下面举个最简单的例子,平常工作当中肯定比这个sql复杂的多,在这只是把这个易错点呈现出来,他可能是一个复杂sql出错的小的 不容易被发现的一个问题。

oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)_第1张图片

上面是一个很简单表的所有数据。area_num 区域编码 area_name 区域名称 delflag 有无效标识 1有效 0无效(其中淮北 和宣城的delflag为null)。

现在想找出有效的那些区域信息,所以用下面的语句:

oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)_第2张图片

上面的结果中没有淮北和宣城 跟预想中的不一样 一开始以为是 delflag不为0的所有应该都被查询出来 包括淮北和宣城。

事实上 淮北和宣城 delflag的字段是 null值。在oracle里面null值得概念:

NULL是数据库中特有的数据类型,当一条记录的某个列为NULL,则表示这个列的值是未知的、是不确定的。既然是未知的,就有无数种的可能性。因此,NULL并不是一个确定的值。

所以null值(不确定的值) 并不符合 !='0' 这个 条件。同样下面语句也是这样。

oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)_第3张图片

二、无结果

无结果其实就是一个select查询没有结果集(不是null,而是没有结果)

结果为null:oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)_第4张图片

无结果:oracle开发系列(一)让人抓狂的错误之null值与无值(无结果)_第5张图片

表面看很的清楚明白,但是到了实际应用中可能 会容易搞错。

下面是示例的存储过程:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
create or replace function getProceessidAllDealBySkf_l(proceessid in number)
   return varchar2 as
   cursor pcursor is (
     select distinct t.orgid, t.oper_name
       from tssa_his_dsg.wh_common_busilog_td t
      where t.processinstid = proceessid); --取操作日志表某个工单流程proceessid的操作人所属机构id,和操作名称
   orgidCursor   pcursor%rowtype; --定义类型为pcursor行数据的 变量
   orgid_var     varchar2(20); --存放操作人机构id变量
   returnflag    varchar2(20); --返回的标志位
   orgseqflag    varchar2(50); --操作人机构id及其所有父id 串起来字符
   skforgflag    varchar2(20); --存放操作人机构id变量
   count_var     number; --存放统计数字变量
   oper_name_var varchar2(100); --操作名称
begin
   returnflag    := '1' ; --返回值初始化为1
   orgseqflag    := null ; --初始化
   skforgflag    := null ; --初始化
   count_var     := 0; --初始化
   oper_name_var := null ; --初始化
   open pcursor; --打开游标
 
   loop
     fetch pcursor
       into orgidCursor; --把游标数据放进pcursor变量
     exit when pcursor%notfound;
   
     orgid_var     := orgidCursor.orgid; --从orgidCursor变量取值到orgid_var
     oper_name_var := orgidCursor.oper_name; --从orgidCursor变量取值到oper_name_var
   
     if (orgid_var is null ) then --orgid_var是可能为空的 表里面t.orgid为空
       null ;
     else
       select count (1)
         into count_var
         from tssa_dsg.eosorg_t_organization b,
              ( select a.*
                 from tssa_dsg.bndict_t_dictionary a
                where a.BUSINTYPEID = 'WH_CH_ORAPROPERTY'
                  and a.status = '0' ) a
        where b.orgproperty = a.businid(+)
          and b.orgid = orgid_var; --统计操作日志表的机构id是否在机构静态表里
       if (count_var > 0) then --在里面
         select t.orgseq
           into orgseqflag
           from tssa_dsg.eosorg_t_organization t
          where t.orgid = orgid_var
         --取orgseqflag
         ;
         select a.businname
           into skforgflag
           from tssa_dsg.eosorg_t_organization b,
                ( select a.*
                   from tssa_dsg.bndict_t_dictionary a
                  where a.BUSINTYPEID = 'WH_CH_ORAPROPERTY'
                    and a.status = '0' ) a
          where b.orgproperty = a.businid(+)
            and b.orgid = orgid_var; --取组织分类
       
         if (orgseqflag like '99999.7676.%' or skforgflag = '省客服' or
            (skforgflag != '省客支' and skforgflag != '省层面' and
            oper_name_var = '话务员追加信息' )) then
           null ;
         else
           returnflag := null ; --不满足id条件 置返回值为null
         end if;
       end if;
     end if;
   end loop;
   close pcursor;
   return returnflag;
end ;
上面这个过程的作用就是根工单流程id 返回该工单是否只经过某个特定组织机构的人处理的标志。

操作日志表的orgid有为空的情况。
if(orgid_var is null) 这个条件 判断如果为空 视该记录无效,不参与判断(业务要求)。

如果不加这个条件 (且没有

?
1
2
3
4
5
6
7
8
9
select count (1)
         into count_var
         from tssa_dsg.eosorg_t_organization b,
              ( select a.*
                 from tssa_dsg.bndict_t_dictionary a
                where a.BUSINTYPEID = 'WH_CH_ORAPROPERTY'
                  and a.status = '0' ) a
        where b.orgproperty = a.businid(+)
          and b.orgid = orgid_var; --统计操作日志表的机构id是否在机构静态表里
) 

下面这个语句

?
1
2
3
4
select t.orgseq
           into orgseqflag
           from tssa_dsg.eosorg_t_organization t
          where t.orgid = orgid_var
查出来是没有结果的 就是无值
?
1
into orgseqflag
就会报错(调试会报错,直接运行不报错) 直接 跳出 loop 给 return 一个null 值 是不符合业务要求的。
?
1
2
3
4
5
6
7
8
9
10
select count (1)
         into count_var
         from tssa_dsg.eosorg_t_organization b,
              ( select a.*
                 from tssa_dsg.bndict_t_dictionary a
                where a.BUSINTYPEID = 'WH_CH_ORAPROPERTY'
                  and a.status = '0' ) a
        where b.orgproperty = a.businid(+)
          and b.orgid = orgid_var; --统计操作日志表的机构id是否在机构静态表里
if (count_var > 0) then --在里面
上面这个条件作用跟if(orgid_var is null)是一样的 是忽略 操作日志表的机构id不在机构静态表里的情况。

你可能感兴趣的:(Oracle)