打印NULL值列名称

时间:2017-07-15 07:07:42

标签: oracle oracle11g oracle10g oracle-sqldeveloper

我有一个包含ColA,...,ColE列的表,如下所示。我需要检查每条记录,并在名为Comments

的另一个现有列中显示具有NULL值的列名
ColA   ColB    ColC    ColD   ColE   Comments
----   ----    -----   ----   ----   ------------------------------
1      7       3       4      NULL   NULL VALUE In ColE      
2      9       NULL    12     NULL   NULL VALUE in ColC, ColE   
3      NULL    NULL    NULL   10     NULL VALUE IN ColB, Colc, ColD 

输出应与上述结果集中的Comments列类似。

2 个答案:

答案 0 :(得分:1)

这可以仅使用普通SQL(无过程或函数等)来完成,例如使用MERGE语句。一个完整的会话,从设置表开始,插入值,添加一个用于注释的列,然后是MERGE语句,结果"在"之前""""如下所示。

我添加了一行数据,其中没有NULL个值。你总是需要这样的东西来测试解决方案:当连续没有 NULL值时,它是否正常工作?

真正的工作是在下面的解决方案中标记为x的子查询中完成的。首先我unpivot来自原始表的数据(添加ROWID,以便稍后我可以识别每一行)。 UNPIVOT需要Oracle 11.1或更高版本;我还使用需要Oracle 11.2或更高版本的LISTAGG。您使用oracle11goracle10g标记了自己的帖子,因此我不知道您拥有什么,在任何情况下11g都是营销名称;正确的版本是11.1或11.2(或者,真的,11.2.0.4.0和类似)。您可以使用select * from v$version找到您的版本。

如果您没有Oracle 11.2,则可以使用其他工具(分层查询或XMLAGG等)完成字符串聚合 - Stack Overflow充满了关于如何完成的问题。同样,如果您没有Oracle 11.1,则可以使用交叉连接进行非透视;我没有检查,但我认为Stack Overflow上有很多关于它的问题。这两项操作都是标准的,与您的问题无关;如果您需要帮助,请先搜索本网站,如果您遇到困难,请回信。

所以,回到我的方法。我忽略了数据,跟踪rowid。在unpivot操作中,我包含空值(这不是默认值,因此需要include nulls)。然后从结果中我只保留值为NULL的行。然后,我按RID进行分组,并与LISTAGG汇总。这为x操作准备了子查询MERGE,这是此时的标准。

关于效率的说明我在评论中询问了OP是否应该首选快速执行或简化解决方案(更容易维护)。 OP表示易于维护更为重要。下面的解决方案更清楚,但由于以下原因而无效。在原始表中,五列中的值已经"分组"事实上它们出现在同一行。 Unpivoting失去了这些信息;然后我们必须再次按ROWID分组,以创建LISTAGG字符串并准备MERGEGROUP BY操作很昂贵,如果我们编写的代码没有分解输入行,就不需要它。但是,尽管可能,编写一个不会破坏输入行的解决方案会更加混乱,尤其是当列数增加时。

<强> SETUP

create table tbl(cola number, colb number, colc number, cold number,cole number);
insert into tbl(cola, colb, colc, cold, cole) values (1,    7,    3,    4, NULL);  
insert into tbl(cola, colb, colc, cold, cole) values (2,    9, NULL,   12, NULL);
insert into tbl(cola, colb, colc, cold, cole) values (3, NULL, NULL, NULL,   10);
insert into tbl(cola, colb, colc, cold, cole) values (0,    1,    2,    3,    5);
commit;

alter table tbl add (comment_about_nulls varchar2(1000));

select * from tbl;

COLA COLB COLC COLD COLE COMMENT_ABOUT_NULLS                    
---- ---- ---- ---- ---- ----------------------------------------
   1    7    3    4                                              
   2    9        12                                              
   3                  10
   0    1    2    3    4

<强>解

merge into tbl
using (
        select   rid, listagg(colname, ', ') within group (order by colname) str
        from     (select rowid as rid, cola, colb, colc, cold, cole from tbl)
        unpivot  include nulls (val for colname in 
                          (cola as 'ColA', colb as 'ColB', colc as 'ColC',
                                           cold as 'ColD', cole as 'ColE'))
        where    val is null
        group by rid
      ) x
  on (tbl.rowid = x.rid)
when matched then update
  set tbl.comment_about_nulls = 'NULL VALUE IN ' || x.str
;

select * from tbl;

COLA COLB COLC COLD COLE COMMENT_ABOUT_NULLS                    
---- ---- ---- ---- ---- ----------------------------------------
   1    7    3    4      NULL VALUE IN ColE                      
   2    9        12      NULL VALUE IN ColC, ColE                
   3                  10 NULL VALUE IN ColB, ColC, ColD          
   0    1    2    3    5  

答案 1 :(得分:0)

是你想要的代码吗?

declare 
  v_table_name  varchar2(31)  := 'MYTABLE';
  v_sql         varchar2(4000);
  v_columnName  varchar2(100);
  v_col         pls_integer; 
  cm            varchar2(1); 
  i             pls_integer := 0;   
begin
for b in ( select rownum rnum, t.rowid rid, t.* from mytable t order by rownum )
loop
 begin
 for c in ( select t.* from user_tab_columns t where t.table_name = v_table_name order by column_name ) 
 loop    
   v_sql := 'select ' || c.column_name  || ' from ' || v_table_name || ' t where t.rowid = '''||b.rid||'''';
   execute immediate v_sql into v_col; 
   if nvl(v_col,0)=0 then     
     if i>0 then cm:=','; end if;
     v_columnName := v_columnName||cm||c.column_name; 
     i:=+1;
   end if; 
 end loop;
    dbms_output.put_line(rpad(nvl(to_char(b.rnum),'NULL'),5,' ')||' '||rpad(nvl(to_char(b.cola),'NULL'),5,' ')||' '||rpad(nvl(to_char(b.colb),'NULL'),5,' ')||' '||rpad(nvl(to_char(b.colc),'NULL'),5,' ')||' '||rpad(nvl(to_char(b.cold),'NULL'),5,' ')||' '||rpad(nvl(to_char(b.cole),'NULL'),5,' ')||' '||'NULL VALUE In '||v_columnName); 
    v_columnName := null; i := 0; cm := null;
  exception when no_data_found then continue;
 end; 
end loop; 
end; 

将colA-E视为数字类型,并且mytable中不存在注释。