I need to return all records if input parameter is null.
I\'ve written a simple query
declare
l_sql varchar2(100);
i number := 1;
begin
l_sq
IS NULL suppresses the index usage. Because NULL values are not indexed.
There are two ways to make the use of index with IS NULL :
1.BITMAP index. However, more applicable in OLTP systems.
2.My favourite way, and nice to demonstrate. We could make the leaves of the b-tree index a constant. Thus, making use of index while querying for NULL. Basically, the NULLs are all together, at the top/bottom of the index. Oracle can use the index forwards or backwards, so doesn't really matter. And it does a full scan of the index.
I have answered a similar question here http://www.orafaq.com/forum/mv/msg/194746/625371/#msg_625371
The first scenario won't use the index due to the OR is null condition :
SQL> SELECT * FROM PROD_NEW;
PROFILE_TYPE
---------------
Prod
Prodparallel
Prod
SQL> CREATE INDEX PROD_NEW_I1 ON PROD_NEW
2 (PROFILE_TYPE
3 );
Index created.
SQL> EXPLAIN PLAN FOR SELECT * FROM PROD_NEW WHERE PROFILE_TYPE = 'Prod' OR PROFILE_TYPE IS NULL;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2121244107
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 15 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| PROD_NEW | 3 | 15 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("PROFILE_TYPE" IS NULL OR "PROFILE_TYPE"='Prod')
13 rows selected
Let's make the leaves constant :
SQL> DROP INDEX PROD_NEW_I1;
Index dropped.
SQL> CREATE INDEX PROD_NEW_I1 ON PROD_NEW
2 (PROFILE_TYPE,1
3 );
Index created.
SQL> EXPLAIN PLAN FOR SELECT * FROM PROD_NEW WHERE PROFILE_TYPE = 'Prod' OR PROFILE_TYPE IS NULL;
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1272076902
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 15 | 1 (0)| 00:00:01 |
|* 1 | INDEX FULL SCAN | PROD_NEW_I1 | 3 | 15 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("PROFILE_TYPE" IS NULL OR "PROFILE_TYPE"='Prod')
13 rows selected.
SQL>