Spending a good amount of time answering the questions on multiple Oracle forums, like OraFAQ, Stack Overflow, OTN, dBforums etc. I could now figure out the most common questions by amateurs in Oracle SQL and PL/SQL. My recent blog posts are focused on such questions. And one among them is “How to find all columns having at least a NULL value from all tables in the schema“.
Now, in SQL it would be a huge task to manually code all the column names in the WHERE clause to check IS NULL condition. However, the manual effort could be minimized to a great extent using an UDF(user defined function) and query on dynamic view ALL_TAB_COLUMNS. Let me demonstrate using the SCOTT schema :
- Create a simple function FIND_NULL_COL, it would return 1 if found any NULL value in any column.
SQL> CREATE
2 OR REPLACE FUNCTION FIND_NULL_COL(TABLE_NAME VARCHAR2, COLUMN_NAME VARCHAR2)
3 RETURN NUMBER
4 IS cnt NUMBER;
5 BEGIN
6 cnt :=1;
7 EXECUTE immediate 'select count(1) from '||table_name||' where '||column_name||' is not null' INTO cnt;
8 RETURN
9 CASE
10 WHEN CNT=0 THEN
11 1
12 ELSE
13 0
14 END;
15 END;
16 /
Function created.
- Now, use the UDF in your SQL.
SQL> set pagesize 1000
SQL> column owner format A10;
SQL> column column_name format A20;
SQL> COLUMN TABLE_NAME FORMAT A20;
SQL> column n format A1;
SQL> SELECT c.OWNER,
2 c.TABLE_NAME,
3 c.COLUMN_NAME,
4 C.NULLABLE,
5 FIND_NULL_COL(c.TABLE_NAME,c.COLUMN_NAME) null_status
6 FROM all_tab_columns c
7 WHERE c.OWNER=USER
8 AND c.TABLE_NAME LIKE '%'
9 ORDER BY C.OWNER,
10 C.TABLE_NAME,
11 C.COLUMN_ID
12 /
OWNER TABLE_NAME COLUMN_NAME N NULL_STATUS
---------- -------------------- -------------------- - -----------
SCOTT BONUS ENAME Y 1
SCOTT BONUS JOB Y 1
SCOTT BONUS SAL Y 1
SCOTT BONUS COMM Y 1
SCOTT DEPT DEPTNO N 0
SCOTT DEPT DNAME Y 0
SCOTT DEPT LOC Y 0
SCOTT EMP EMPNO N 0
SCOTT EMP ENAME Y 0
SCOTT EMP JOB Y 0
SCOTT EMP MGR Y 0
SCOTT EMP HIREDATE Y 0
SCOTT EMP SAL Y 0
SCOTT EMP COMM Y 0
SCOTT EMP DEPTNO Y 0
SCOTT SALGRADE GRADE Y 0
SCOTT SALGRADE LOSAL Y 0
SCOTT SALGRADE HISAL Y 0
18 rows selected.
SQL>
So, NULL_STATUS “1” is the list of table names and respective column names which has at least a NULL value.
You could also add more filters to the where clause :
SQL> CREATE OR REPLACE
2 FUNCTION FIND_NULL_COL(
3 TABLE_NAME VARCHAR2,
4 COLUMN_NAME VARCHAR2)
5 RETURN NUMBER
6 IS
7 cnt NUMBER;
8 BEGIN
9 CNT :=1;
10 EXECUTE IMMEDIATE 'select count(1) from '
11 ||TABLE_NAME||' where ' ||COLUMN_NAME||' is not null
12 and deptno = 20' INTO cnt;
13 RETURN
14 CASE
15 WHEN CNT=0 THEN
16 1
17 ELSE
18 0
19 END;
20 END;
21 /
Function created.
SQL> SET pagesize 1000
SQL> column owner format A10;
SQL> column column_name format A20;
SQL> COLUMN TABLE_NAME FORMAT A20;
SQL> column n format A1;
SQL> SELECT c.OWNER,
2 c.TABLE_NAME,
3 c.COLUMN_NAME,
4 C.NULLABLE,
5 FIND_NULL_COL(c.TABLE_NAME,c.COLUMN_NAME) null_status
6 FROM all_tab_columns c
7 WHERE C.OWNER =USER
8 AND c.TABLE_NAME = 'EMP'
9 ORDER BY C.OWNER,
10 C.TABLE_NAME,
11 C.COLUMN_ID
12 /
OWNER TABLE_NAME COLUMN_NAME N NULL_STATUS
---------- -------------------- -------------------- - -----------
SCOTT EMP EMPNO N 0
SCOTT EMP ENAME Y 0
SCOTT EMP JOB Y 0
SCOTT EMP MGR Y 0
SCOTT EMP HIREDATE Y 0
SCOTT EMP SAL Y 0
SCOTT EMP COMM Y 1
SCOTT EMP DEPTNO Y 0
8 rows selected.
SQL>
If you do not want to create the function, then there is another way to get the list of columns having NULL value. Using the *_TAB_COLUMNS view. However, you MUST gather statistics before querying the view to get accurate results.
SQL> EXEC DBMS_STATS.gather_schema_stats('SCOTT');
PL/SQL procedure successfully completed.
SQL>
SQL> SELECT t.table_name, t.column_name
2 FROM user_tab_columns t
3 WHERE t.nullable = 'Y'
4 AND t.num_distinct = 0;
TABLE_NAME COLUMN_NAME
---------- ------------
BONUS ENAME
BONUS JOB
BONUS SAL
BONUS COMM
CLASS NAME
CLASS TIME
CLASS ROOM
CLASS FID
8 rows selected.
SQL>
Hope it helps!
Filed under: Oracle SEARCH/SORT/COMPARE functions Tagged: all null columns, column with null values, null columns in table, NULL value
