Reputation: 315
I created an index called Z7 and I want to use it in a SELECT statement like this:
SELECT * FROM Employees WITH (INDEX(Z7)) WHERE First_Name NOT LIKE ('J%');
But it shows me this error:
ORA-00933: SQL command not properly ended
Upvotes: 1
Views: 9257
Reputation: 21053
Contrary to the LIKE
predicate that can be resolved with a index range scan there is no index access path in Oracle that would implement a NOT LIKE
that would need to do two range scans before and after your LIKE value.
Let's illustrate it in this setup with a table that has only one row satisfying your not like predicate.
create table Employees as
select 'J'||rownum as First_Name, lpad('x',1000,'y') pad from dual connect by level <= 10000
union all
select 'Xname', 'zzzzz' from dual;
create index Z7 on Employees (First_Name);
The query
SELECT * FROM Employees WHERE First_Name NOT LIKE ('J%');
performs as expected a FULL TABLE SCAN
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 37 | 37259 | 398 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMPLOYEES | 37 | 37259 | 398 (1)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FIRST_NAME" NOT LIKE 'J%')
You may hint Oracle to use index as follows (note that your syntax FROM Employees WITH (INDEX(Z7)) WHERE
is wrong and causing your error!)
SELECT /*+ index(Employees Z7) */ * FROM Employees WHERE First_Name NOT LIKE ('J%');
This will indeed cause the index usage, but not in the sence you probablly intended.
If you examines the execution plan you'll see the INDEX FULL SCAN
, that means, Oracle walks through the complete index from A
to Z
, filter the entires in the index that are not like
your predicates (see the FILTER
in the plan below) and for the selected keys access the table.
So generally you'll be not happy with this plan for a large index as it will take substantially longer that the full table scan.
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9433 | 9276K| 2912 (1)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES | 9433 | 9276K| 2912 (1)| 00:00:01 |
|* 2 | INDEX FULL SCAN | Z7 | 9433 | | 25 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("FIRST_NAME" NOT LIKE 'J%')
See here how to produce the execution plan for the query
Upvotes: 3