我有非常大的 Oracle 表,其中有许多与我使用的每个过滤器无关的列。
我想在 Oracle 中编写一个查询或函数,它返回只有空值的列的名称,或者返回不为空的列的名称。
如果您只想查找始终为空的列,您可以运行此查询创建的查询,那些值为 0 的列为空。
select 'select '
|| listagg('count(' || column_name || ') as ' || column_name, ', ')
within group (order by column_id)
|| ' from my_table;'
from user_tab_columns
where table_name = 'MY_TABLE'
这是一个要演示的SQL Fiddle 。
如果您想要列的名称,则必须使用 PL/SQL。这个函数将返回一个逗号分隔的列名列表,当然你也可以返回一个用户定义的类型等。
create or replace function null_cols( P_TableName varchar2 ) return varchar2 is
l_cols varchar2(32767);
l_result number;
begin
for i in ( select column_name
from user_tab_columns
where table_name = upper(P_TableName)
) loop
execute immediate 'select count(' || i.column_name || ')
from ' || P_TableName
into l_result;
if l_result = 0 then
l_cols := l_cols || i.column_name || ', ';
end if;
end loop;
return l_cols;
end;
/
这是对同一个SQL Fiddle的扩展,其中添加了该函数。
我必须补充一点,如果您接受用户输入以使用该功能,您应该使用该dbms_assert
包来帮助避免 SQL 注入。
您可以使用以下查询来识别相同的,请确保您收集统计信息以获得正确的结果
select table_name, column_name
from user_tab_cols
where table_name = 'MY_TABLE'
and NUM_DISTINCT = 0
and NUM_NULLS > 0
更新 1: - 如果您定期收集统计数据(不是 100% 统计数据),您可以使用 Ben 的答案并对其进行优化。下面将减少需要检查的列数
for i in ( select column_name
from user_tab_columns
where table_name = upper(P_TableName)
and num_distinct=0 and num_nulls > 0
) loop