查询以动态方式查找表中没有数据的列

时间:2016-03-03 09:09:49

标签: sql oracle connect-by

我编写了一个Query来查找没有动态表中数据的列。 但是它只用rownum = 1给出输出,这也是不正确的。

WITH x AS (SELECT column_name FROM all_tab_cols 
WHERE OWNER='HR' AND table_name='EMPLOYEES' AND ROWNUM=1)     
SELECT X.column_name,count(X.column_name)
FROM EMPLOYEES,X
/*CONNECT BY LEVEL <= (SELECT count(1) FROM all_tab_cols 
WHERE OWNER='HR' AND table_name='EMPLOYEES')*/
group by X.column_name;

COLUMN_NAME                    COUNT(X.COLUMN_NAME)   
------------------------------ ---------------------- 
EMPLOYEE_ID                    20  

当我尝试使用level使其成为动态时,它会失败。

WITH x AS (SELECT column_name FROM all_tab_cols 
WHERE OWNER='HR' AND table_name='EMPLOYEES' AND ROWNUM=level)     
SELECT X.column_name,count(X.column_name)
FROM EMPLOYEES,X
CONNECT BY LEVEL <= (SELECT count(1) FROM all_tab_cols 
WHERE OWNER='HR' AND table_name='EMPLOYEES')
group by X.column_name;
  

命令行错误:14列:5       错误报告:       SQL错误:ORA-01788:此查询块中需要CONNECT BY子句       01788. 00000 - “此查询块中需要的CONNECT BY子句”

你是否更正了查询以实现同样的目标?

1 个答案:

答案 0 :(得分:0)

您的查询存在一些问题:

  • with子句中的子查询不会从其他子查询中查看 level
  • 您无法使用where rownum = 2,您必须为此列创建别名并从内部查询中选择它,但在您的情况下不需要此部分,
  • 如果要检查所有列,则根本不需要
  • 分层suqbquery。

更正的查询将是:

with x as (
  select column_name from all_tab_cols 
    where owner='HR' and table_name='EMPLOYEES')
select x.column_name, count(x.column_name) as cnt
  from x, employees group by x.column_name;

...但它始终显示每列employees中所有行的数量。所以如果你想找到哪些列 并非所有数据都已填满,您需要动态解决方案。您可以在变量...where ||'r.column_name' is null中添加v_sql之类的内容:

declare
  v_sql varchar2(1000);
  v_num number;
begin
  for r in (select column_name from all_tab_cols 
            where owner='HR' and table_name='EMPLOYEES'
            order by column_id)
  loop
    v_sql := 'select count('||r.column_name||') from employees';
    execute immediate v_sql into v_num;
    dbms_output.put_line(rpad(r.column_name,30)||' '||v_num);
  end loop;
end;

示例数据和输出:

create table employees (id number(3), name varchar2(10), hire_date date);
insert into employees values (1, 'John', trunc(sysdate));
insert into employees values (2, 'Paul', trunc(sysdate));
insert into employees values (3, 'Mark', trunc(sysdate)-1);
insert into employees values (4, 'Anna', null);

ID                             4
NAME                           4
HIRE_DATE                      3