2012-07-15 46 views
0

我有很大的Oracle表,其中有很多與我使用的每個過濾器無關的列。獲得只有空值列的列名

我想在Oracle中編寫一個查詢或函數,該查詢或函數返回僅具有空值的列的名稱或者非空的列的名稱。

回答

3

如果你只是想發現是始終空,這個查詢創建可以運行查詢的列的列數,那些具有價值列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注入。

+0

添加了一條建議我將字符串連接到的行更改爲「dbms_output.put_line」太重了。儘管如此,它的工作。謝謝 – gilibi 2012-07-15 11:25:04

+0

@gilibi,不管你爲什麼工作,字符串連接只是你如何顯示結果的例子! 'dbms_output.put_line'被限制爲255個字符,因此您必須手動執行某些操作。 – Ben 2012-07-15 11:26:29

0

您可以使用下面的查詢來識別相同的,請確保您收集統計信息爲獲得正確的結果

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 
+0

你必須收集100%的統計數據。這比僅查詢表格的效率低很多。 – Ben 2012-07-15 09:00:06

+0

這將是相關的,如果它是一個生產系統,統計數據將頻繁收集 – psaraj12 2012-07-15 09:12:07

+0

我的觀點是,統計數據收集使用動態抽樣,因此沒有_guarantee_這個查詢的結果是_exactly_正確的,除非你已經收集到100%。如果您收集99.999%,您可能仍然錯過該列中的一個值,這意味着您得到的答案不正確。 – Ben 2012-07-15 09:18:27