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>