0

I have really big Oracle table with many columns that are not relevant to each filter that I use.

I want to write a query or function in Oracle that returns the name of the columns that have only null values or alternatively the name of the columns which are not null.

2 Answers 2

3

If you just want to find the columns that are always null you can run the query that this query creates, those columns that have a value 0 are null.

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'

Here's a SQL Fiddle to demonstrate.

If you want the names of the columns you have to use PL/SQL. This function will return a comma delimited list of column names, but of course you could return a user defined type etc.

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;
/

Here's an extension to the same SQL Fiddle with the function added.

I have to just add that if you're accepting user input in order to use the function you should use the dbms_assert package in order to help avoid SQL Injection.

Sign up to request clarification or add additional context in comments.

2 Comments

It was too massive to I changed the line where the string is concatenated to "dbms_output.put_line". Nevertheless, it's working. thanks
@gilibi, whatever works for you, the string concatenation was only an example of how you could display the result! dbms_output.put_line is limited to 255 characters so you then have to do something manually with it.
0

You can use the following query to identify the same ,Please make sure you gather statistics for getting correct results

    select table_name, column_name
      from user_tab_cols         
                where table_name = 'MY_TABLE'
       and NUM_DISTINCT = 0
       and NUM_NULLS > 0

UPDATE 1:- IF your are gathering statistics regularly (not 100% statistics),you can use Ben's answer and also optimize it. The below would reduce the number of columns which needs to be checked

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

3 Comments

You have to gather 100% statistics. Making this a lot less efficient than just querying the table.
It will be relevant if it is a production system where statistics would be gathered frequently
My point is that the statistics gathering uses dynamic sampling so there's no guarantee that the results of this query are exactly correct unless you have gathered 100%. If you gather 99.999% you may still miss the one value in that column, which in turn means that the answer you get is incorrect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.