Oracle 打印空值列名
我有一张列有可乐的桌子,科尔如下。我需要检查每个记录,并在另一个名为Comments的现有列中显示具有空值的列名Oracle 打印空值列名,oracle,oracle11g,oracle10g,oracle-sqldeveloper,Oracle,Oracle11g,Oracle10g,Oracle Sqldeveloper,我有一张列有可乐的桌子,科尔如下。我需要检查每个记录,并在另一个名为Comments的现有列中显示具有空值的列名 ColA ColB ColC ColD ColE Comments ---- ---- ----- ---- ---- ------------------------------ 1 7 3 4 NULL NULL VALUE In ColE 2 9 NU
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
输出应该类似于上述结果集中的
注释列。这是您想要的代码吗
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中不存在注释。这可以仅使用普通SQL(无过程或函数等)来完成,例如使用MERGE
语句。一个完整的会话,从设置表开始,插入值,再添加一列注释,然后是MERGE
语句,结果“before”和“after”如下所示
我又添加了一行数据,其中没有NULL
值。您总是需要这样的东西来测试解决方案:当一行中有noNULL
值时,它是否正常工作
真正的工作是在下面的解决方案中标记为x
的子查询中完成的。首先,我unpivot
原始表中的数据(添加ROWID
,以便以后识别每一行)UNPIVOT
需要Oracle 11.1或更高版本;我还使用要求Oracle 11.2或更高版本的listag
。你用oracle11g
和oracle10g
标记了你的帖子,所以我真的不知道你有什么,而且在任何情况下11g
都是营销名称;正确的版本是11.1或11.2(或者,实际上是11.2.0.4.0及类似版本)。您可以使用从v$version
中选择*来查找您的版本
如果没有Oracle 11.2,可以使用其他工具(分层查询或XMLAGG
等)完成字符串聚合-堆栈溢出充满了关于如何完成的问题。类似地,如果您没有Oracle11.1,则可以通过交叉连接来取消激活;我没有检查,但我想关于堆栈溢出也有很多问题。这两种操作都是标准的,与您的问题无关;如果您需要帮助,请从搜索此网站开始,如果遇到困难,请回信
那么,回到我的方法。我取消打印数据,跟踪rowid
。在unpivot
操作中,我包含空值(这不是默认值,因此需要include nulls
)。然后根据结果,我只保留值为NULL
的行。然后我按RID
分组,并用listag
进行聚合。这将为MERGE
操作准备子查询x
,这是超出此点的标准操作
关于效率的注意事项我在一篇评论中询问了OP是否应该首选快速执行或简单的解决方案(更易于维护)。OP表示,更重要的是易于维护。下面的解决方案更清晰,但由于以下原因,它不是有效的。在原始表中,五列中的值已按它们出现在同一行的事实“分组”。取消激励会丢失此信息;然后我们必须再次按ROWID
分组,以创建listag
字符串并准备MERGE
。groupby
操作成本很高,如果我们编写的代码没有分解输入行,就不需要它。但是,编写一个不分解输入行的解决方案(虽然可能)会更混乱,尤其是当列数增加时
设置
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
对您来说,什么更重要:代码的简单性(易于维护),还是效率(执行速度)?不要两者都说!有很多方法可以有效地解决这个问题,但是代码更麻烦。请澄清:你所说的“注释”是什么意思?您的表(保存在磁盘上)有这样的列吗?还是只需要在SELECT
查询的输出中使用该列?(与之相反:该列确实存在,您需要更新它并将结果保存在磁盘上。)我已经创建了一个名为Comments的列-如果任何行具有null,并且该列名应该在Comments列中更新为-null值,则在ColE中。。。。如果有更多的列,那么所有的人都应该对代码的简单性有更多的共谋…ColA ColB ColC ColD ColE-----------1 7 3 4 NULL 2 9 NULL 12 NULL 3 NULL NULL NULL 10我的结果应该是这样的,请不要列同时包含number和Varchar值Result NULL VALUE In ColE NULL VALUE In ColC,ColB,ColC,ColDThanks中ColE NULL VALUE for响应。下面是我所期望的输出ColB ColC ColE ColD ColE-------1 7 3 4 NULL 2 9 NULL 12 NULL 3 NULL NULL NULL 10我的结果应该是这样的,请不要列同时包含number和Varchar值ColC中的ColE NULL VALUE、ColB中的ColE NULL VALUE、ColC、ColDpart中的Result NULL VALUE“…”NULL VALUE In“| | v| U columnName”已经代表此(注释)。你真的试过密码吗?只是,我没有为标题部分添加任何代码。这就是我获得输出的方式。请注意,我仍然是SQL的新手1 1 7 3 4空值2 2 9空值12空值3 3空值10空值需要更多的小帮助,我如何将输出更新到我的表各自的记录结果列。谢谢我的同事(数学家),我很欣赏你的解决方案。@mathguy-非常感谢,它按照我的要求工作。感谢您的时间和帮助