Making Oracle Case insensitive
March 13, 2004 - 9pm Central time zone
Reviewer: Getachew G. from Minneapolis, MN USA
Thank you again.
I will test and implement this in 10G in a few months.
I am not sure what the impact will be if I set the
two parameters(nls_comp and nls_sort) at the system
level. But, thank you for providing me with a good information.
Followup March 14, 2004 - 9am Central time zone:
it'll make everything case insensitive will be the impact. Not sure I'd do it system wide, but via
alter sessions in the app or via an on logon trigger -- sure.
no caveat ?!
March 14, 2004 - 2pm Central time zone
Reviewer: Gabe
Regarding #2 and the answer "in 10g, yes" ...
My observations/questions:
1. I'm assuming statistics were gathered automatically (10g feature)
2. Is RBO still available in 10g?
3. I know Cardinality is an estimation ... but why wouldn't the optimizer estimate on the side of
caution with "Card=<#rows in table>" (or some function of it) rather than "Card=1"?
4. What was the point of first_rows? For the method to be deterministic, the FBI has to be used
(hints are just ... hints). In fact, any query against a table with 3 rows should probably result
in a FT ... here the FT would translate in a bug in the application.
I'm highly suspicious of relying on indexes for business logic when querying Oracle (for DML? ...
yes, FTIs are very useful as you show in your last book) ... is my suspicion unfounded? Can Oracle
really be forced to always use an index (FBI or not)?
Thanks.
Followup March 14, 2004 - 2pm Central time zone:
1) no, there weren't any
2) yes, but not supported and not by default
3) small table. forced the cbo to guess with the hint so the index would be used.
4) to bias the index, table was too small to use an index "for real" otherwise. I was trying to
demonstrate that "yes, this case insensitive stuff can be as efficient as case sensitive, given the
correct indexes are in place"
I'm not relying on the index for anything here. I was merely demonstrating that the index can in
fact be used transparently.
ops$tkyte@ORA10G> select /*+ FULL(t) */ * from t where data = :x;
DATA
--------------------
Hello
HeLlO
HELLO
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1 Bytes=12)
1 0 TABLE ACCESS (FULL) OF 'T' (TABLE) (Cost=3 Card=1 Bytes=12)
Full scans work just as well. I would never suggest on relying on a query plan for getting data
"just so". Either plan works the same (although they could return the data in very different order
of course! but if you need a certain order, that is what order by is all about)
indeed ...
March 14, 2004 - 3pm Central time zone
Reviewer: Gabe
"I'm not relying on the index for anything here"
I can see now you don't.
So it is all about these:
alter session set nls_comp=ansi; --works in 9i
alter session set nls_sort=binary_ci;
Guess the "binary_ci" is the thing that makes this a 10g solution only. I'll look it up in the
docs.
Thanks.
Followup March 14, 2004 - 7pm Central time zone:
binary_CaseInsensitive
^ ^

March 14, 2004 - 11pm Central time zone
Reviewer: Bhagat Singh from India
Hello Tom,
may be most of the peoply might not be having 10g right now but I was astonished to see the answer,
I was expecting some function based indexes and all any special reason for this.
regards
Bhagat Singh
Followup March 15, 2004 - 7am Central time zone:
curious -- you did see a function based index:
ops$tkyte@ORA10G> create index t_idx on
2 t( nlssort( data, 'NLS_SORT=BINARY_CI' ) );
but any special reason for what exactly?
LIKE operator for case-insensitive queries
March 15, 2004 - 5pm Central time zone
Reviewer: Gary from Sydney, Australia
Haven't got 10g, so cannot verify this, but it has been reported on another website
( http://www.quest-pipelines.com/pipelines/dba/index.asp , that while = (and presumably <, > etc) all pick up on this case-insensitive setting, the LIKE
operator does not.
Also changing the nls_sort parameter means you cannot mix case-sensitive and case-insensitive
predicates in a query.
This means you have a choice of
1) Have both case-sensitive and case-insensitive indexes
2) Risk some queries not have the correct sensitivity index available on some predicates
3) Choose whether the database as a whole should be case-sensitive or insensitive, and design your
indexes accordingly
Personally, I still prefer the 'old-tech' UPPER(col)='...' with a function based index on the
UPPER(col).
That allows the case-insensitivity to be applied at the lowest level so has more flexibility.
For example, with a table with Address, City, State and Zip Code, you could decide to be
case-insensitve for Address, but case-sensitive for state because you store them all in upper case.
Followup March 15, 2004 - 6pm Central time zone:
correct but an Oracle Text index can (even in 9i, 8i) do that.
non 10g solution
July 9, 2004 - 7am Central time zone
Reviewer: Dez from Netherlands
Recently I encountered the same problem and we couldnt use Function Based Indexes or ad an extra
index. The way Oracle Forms translates Queries on Case Insensitive fields gives another option:
select * from t where lower(data)='hello' and (data like 'h%' or data like 'H%')
This way the query will still run alot faster without using Funtion Based Index
Hopefully it will be usefull.
an approach for oracle 9
August 12, 2004 - 2pm Central time zone
Reviewer: Henry Rabinowitz from New York, NY
I read in the oracle 9 documentation that one can get case insensitive comparison by saying
alter session set NLS_COMP=ANSI;
alter session set NLS_SORT=GENERIC_BASELETTER;
This does appear to work for queries like
select * from emp where ename = 'miller'
But it does not appear to work with queries using LIKE, such as
select * from emp where ename like 'mill%'
This does not work for LIKE operators
August 13, 2004 - 12pm Central time zone
Reviewer: Nags from Boston
When doing case insensitive searches, the parameters for 9i work, but we cannot use LIKE operators.
How to make it work ?
These are the parameters that we are using..
alter session set nls_comp=ansi;
alter session set nls_sort=GENERIC_BASELETTER;
Followup August 13, 2004 - 5pm Central time zone:
they do not work with like, even in 10g --
Our application is totally case insensitive
August 13, 2004 - 12pm Central time zone
Reviewer: Nags from Boston
I forgot to mention.. our application is totally case insensitive. That means we always do case
insensitive searches.
Followup August 13, 2004 - 5pm Central time zone:
oracle text is totally case insensitive as well -- you might consider using the power of that - it
can do tons more than "like"
Case sensitivity an issue for our application
August 14, 2004 - 12am Central time zone
Reviewer: Nags from Boston
Please let me explain the issue we have, and I would really appreciate if you can help me.
Our application is web based and has been designed to work with both Oracle and SQL Server. It is
a licensing system.
The entire application logic and processing of data is being done in the application. (This design
is not under my control) We use no procedures, functions, triggers etc. Some how I forced my
management to use unique constraints, referential integrity. We have all columns as NVARCHAR2 &
NTEXT. When doing searches, for eg. COMPANY_NAME, we added a shadow column, which the application
makes sure that it keeps it up to date. For all other searches, we do have indexes on the
necessary columns, but all are case insensitive searches (on SQL Server) We do not use UPPER
function at all.
If we have to search for First name, last name, and in the admin section configure the drop downs
for country, provinces etc. When we switched to oracle, all the searches started failing. I
didn't make sense for us to tell the user that the searches are case sensitive, because the user
does not care.
Can I still have a work around in doing case insensitive searches. I cannot use oracle text
because my management thinks that dba should have very little knowledge or no knowledge of the
database to install our product.
Followup August 14, 2004 - 1pm Central time zone:
<quote>
Our application is web based and has been designed to work with both Oracle and
SQL Server. It is a licensing system.
</quote>
ugh.
can you tell me the name of this product, so I can avoid it, it'll work maybe OK on a single
database, horribly on the other. no matter which one, it will not exploit any feature of a big
piece of software companies pay money for and expect to be used.
(the best was to be database "flexible" -- use only stored procedures, outlaw
insert/update/delete/select in the code outside of the database. use the database to death)
Apparently you didn't design to work with both Oracle and SQLServer. Your second to last paragraph
"proves that".
Sorry, Oracle <> SQLServer (and it goes the other way as well, there are thousands of things we do
that they do not). database independence, the holy grail. I lol everytime I see it. what a waste
of good money. I'd rather see you pick one or the other database here and just *use it*.
Wonder how you work in a multiuser situation, given that our locking models are as orthogonal as
you can get. Love to look at some of your code, I'm sure I could break every single business rule
you *think* you are enforcing in the client and really mess up your data integrity :)
Case sensitivity an issue for our application
August 14, 2004 - 1pm Central time zone
Reviewer: Nags from Boston
I totally agree to all the issues that you put forth. Its not my decision, my CTO decides it. We
did have a lot of data integrity issues, but his argument is
"is we add restrictions on the database it would be difficult if the restriction changes for a
different client"
Our application is entirely based on some configuration tables.
Our application was first designed for Oracle only. But when oracle became expensive (about 1
million to own) about 3 years back my CTO decided to make our application portable to both oracle
and sql server. And finally our application became more oracle less sql server.
We had lot of issues with multiuser and locking. And a lot of performance issues. I am trying to
work with the parameters I have.
Is there an alternative in oracle for case insensitive searches or we just have to live with it ?
Followup August 14, 2004 - 2pm Central time zone:
CTO in this case means "chief 'totally not clued in' officer"? What is a "C" level person doing
making nitty gritty technical decisions that should be engineering level decisions. oh well. I
won't get started.
Expensive? We cost less than SQLServer given the amount of functionality you are using (eg: none).
Oacle Standard Edition is cheaper than SQL server. I think your CTO read a magazine maybe.
1 million would be a non-discounted 50 cpu license. Your application runs on a 50 cpu machine
(nah, nix that, you are running on windows). I just went to store.oracle.com and ordered me 5
named users for $1,500 -- upgraded to $1,830 to get all software updates and complete support.
Use the shadow column trick everywhere
or
start using the database -- function based indexes for example.
Case sensitivity an issue for our application
August 14, 2004 - 2pm Central time zone
Reviewer: Nags from Boston
Thanks a lot for your help.
I was talking about Oracle being expensive about 3 years back. Not now. Moreover ours is a
webbased application, hence we could not use named user license.
Based on your suggestion, we will surely revisit the application.
Followup August 14, 2004 - 4pm Central time zone:
we haven't changed pricing drastically in eons. We went from power units to "just by cpu" many
many years ago.
Really, its been that way for a long long time. in 2001, it cost no less, no more. And definitely
not the orders of magnitude you quote.
Even by cpu, you'll find it way comparable with sqlserver.
Setting case insensitive negates indexes ??
October 19, 2004 - 5pm Central time zone
Reviewer: Anton from NZ
Hi Tom.
If I set an Oracle 9iR2 database to be case insensitive ie.
alter session set nls_comp=ansi;
alter session set nls_sort=GENERIC_BASELETTER;
And I have an index on say a name column, will the above setting always cause Oracle to do a full
table scan and not use the index ?
Thanks
sorting on column by number + upper of that
April 13, 2005 - 12pm Central time zone
Reviewer: Jelena from Germany
Hi Tom,
I have two questions about sorting.
Application generates sql and sorting clauses dynamically and usually we get something like:
select a, b, c
from abc_table
order by 3
Now i want to make it order by case-insensitive-on-3rd-col and i did:
select a, b, c
from abc_table
order by upper(3)
but it doesn't work. Is it really applying upper to number 3 and then sorting on nothing??? as it
seems not to sort at all. (with upper(c) it works, but it's difficult to change application)
And second question, to make it work more intelligent way, i wanted to alter database not session,
but it looks as I can only change nls_sort in pfile and need to restart database. As this is 24x7
system, it's not easy, so is there any option like alter system... or alter database set nls_sort,
without restart?
Thank you,
Jelena
Followup April 13, 2005 - 12pm Central time zone:
it would be sorting on the upper(literal)....
sorry, but in order to sort on the UPPER of column 3, column 3 would have to be uppercased.
but what version?
you can change the nls_sort in a session via alter session without restarting.
NLS_COMP
February 2, 2006 - 2pm Central time zone
Reviewer: Deepak Haldiya from FL, USA
Hi Tom,
1. I read in this thread that LIKE operator does not work with case insensitive searches.
I tried the following
alter session set nls_comp=ansi;
alter session set nls_sort=binary_ci ;
SQL> select * from t where data like :x || '%' ;
DATA
--------------------
Hello
HeLlO
HELLO
Correct me if i am wrong in my understanding, but it seems that LIKE works fine, just like =,<,>
etc.
2. What's the importance of this statement:
alter session set nls_comp=ansi;
The default nls_comp is binary. The nls_sort=binary_ci does not work fine nls_comp=binary. Aren't
we doing a binary case insensitive comparison here?
Thanks
Deepak
Followup February 2, 2006 - 2pm Central time zone:
you don't show us what you set :x to, I suspect 'H'.... (and they are all like H% - without CI
processing...)
But look:
ops$tkyte@ORA10GR2> create table t ( data varchar2(20) );
Table created.
ops$tkyte@ORA10GR2> insert into t values ( 'Hello' );
1 row created.
ops$tkyte@ORA10GR2> insert into t values ( 'HeLlO' );
1 row created.
ops$tkyte@ORA10GR2> insert into t values ( 'HELLO' );
1 row created.
ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> variable x varchar2(20)
ops$tkyte@ORA10GR2> exec :x := 'hello';
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> alter session set nls_comp=ansi;
Session altered.
ops$tkyte@ORA10GR2> alter session set nls_sort=binary_ci;
Session altered.
ops$tkyte@ORA10GR2> select * from t where data = :x;
DATA
--------------------
Hello
HeLlO
HELLO
ops$tkyte@ORA10GR2> select * from t where data like :x||'%';
no rows selected
ops$tkyte@ORA10GR2> select * from t where upper(data) like Upper(:x||'%');
DATA
--------------------
Hello
HeLlO
HELLO
LIKE operator Works !!!
February 2, 2006 - 3pm Central time zone
Reviewer: Deepak Haldiya from FL, USA
Hi Tom,
if you set
alter session set nls_comp=linguistic ;
LIKE OPERATOR in the WHERE CLAUSE for case insensitive comparison works. (i forgot to replace ansi
with linguistic in my previous post).
drop table t ;
create table t ( data varchar2(20) );
insert into t values ( 'Hello' );
insert into t values ( 'HeLlO' );
insert into t values ( 'HELLO' );
alter session set nls_comp=linguistic ;
alter session set nls_sort=binary_ci;
variable x varchar2(25)
exec :x := 'hello';
SQL> select * from t where data like :x;
DATA
--------------------
Hello
HeLlO
HELLO
SQL> select * from t where data like :x || '%';
DATA
--------------------
Hello
HeLlO
HELLO
SQL> select * from t where data = :x ;
DATA
--------------------
Hello
HeLlO
HELLO
For NLS_SORT=ANSI option, Oracle Manual says : A setting of ANSI is for backwards compatibility; in
general, you should set NLS_COMP to LINGUISTIC.
Tom, could you please elaborate on what does NSL_COMP=BINARY option do? This is the defualt setting
set by Oracle.
Thanks
Deepak
Followup February 3, 2006 - 1pm Central time zone:
binary is just that - binary, bits and bytes binary. bytes sort byte by byte.
Thanks for the followup, this is the new thing I picked up today myself.
LIKE operator Works !!!
February 8, 2006 - 7am Central time zone
Reviewer: Madhusudan from Pune,India
Thanks Tom & Deepak for very good solution..
Presently working on sqlserver conversion ..
I want to make queries case insensitive...
My boss do not want changes in query so he opted for nls_sort/nls_comp approach
One approach is to use of on logon trigger..
Second approach is to put it in spfile so it will be globally applicable.
I had two queries..
1.
Personally i feel 1st approach will be better as there will be control as i can make it user based
case insensitive.
DECLARE
p_user VARCHAR2(50);
begin
execute immediate
'alter session set nls_date_format = ''DD-MM-YYYY'' ';
SELECT user
INTO p_user
FROM dual;
IF p_user='SA' THEN
execute immediate
'alter session set nls_sort = BINARY_CI';
execute immediate
'alter session set nls_comp = linguistic ';
END IF;
end;
2.
while putting in spfile i had crated spfile added parameters. But there is problem though it shows
correct parameters it's not behaving as expected. Please advice.
SQL*Plus: Release 10.1.0.2.0 - Production on Wed Feb 8 16:52:07 2006
Copyright (c) 1982, 2004, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
sys@DIAMOND> show parameter nls_sort
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY_CI
sys@DIAMOND> show parameter nls_comp
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_comp string linguistic
sys@DIAMOND> ed
Wrote file afiedt.buf
1 select ISDEFAULT ,ISSES_MODIFIABLE, ISSYS_MODIFIABLE ,ISINSTANCE_MODIFIABLE
2* , ISMODIFIED ,ISADJUSTED , ISDEPRECATED from v$PARAMETER where name='nls_sort'
3 /
ISDEFAULT ISSES ISSYS_MOD ISINS ISMODIFIED ISADJ ISDEP
--------- ----- --------- ----- ---------- ----- -----
FALSE TRUE FALSE FALSE FALSE FALSE FALSE
sys@DIAMOND> conn scott/tiger@diamond
Connected.
scott@DIAMOND> select * from t_case where ename like 'king';
ENAME
----------
king
scott@DIAMOND> alter session set nls_sort=BINARY_CI;
Session altered.
scott@DIAMOND> select * from t_case where ename like 'king';
ENAME
----------
KING
King
king
Please guide me..
Followup February 8, 2006 - 8am Central time zone:
http://asktom.oracle.com/~tkyte/Misc/NLSDateFormat.html
that is the reason the init.ora isn't working - the client has some NLS parameter set, hence all
default, the trigger is the correct approach (or in the application itself)
Use regular expressions instead of 'LIKE' for case-insensitivity
February 8, 2006 - 12pm Central time zone
Reviewer: Stewart W. Bryson from Atlanta, GA
The 'i' match parameter tells Oracle to be case-insensitive.
Indexes won't be used for REGEXP_LIKE, though.
SQL> create table t ( data varchar2(20) );
Table created.
Elapsed: 00:00:00.28
SQL> insert into t values ( 'Hello' );
1 row created.
Elapsed: 00:00:00.01
SQL> insert into t values ( 'HeLlO' );
1 row created.
Elapsed: 00:00:00.01
SQL> insert into t values ( 'HELLO' );
1 row created.
Elapsed: 00:00:00.00
SQL> select * from t where regexp_like(data,'hel','i');
DATA
--------------------
Hello
HeLlO
HELLO
3 rows selected.
Elapsed: 00:00:00.02
SQL>
Performance Issues
February 28, 2006 - 2pm Central time zone
Reviewer: Yogesh from Pune, India
Need your opinion
Weather we should be using case insensitive feature, specifically when we are
dealing with high performance sensitive queries and TB size databases?
Followup March 1, 2006 - 7am Central time zone:
It is just a collating character set. Anytime you use anything other than binary you are sort of
doing this already.
Oracle Text and Case Sensitivity
May 10, 2007 - 7pm Central time zone
Reviewer: A reader
I understand that Oracle Text index allows case insensitive search. Is there any way we can make the query either case sensitive or case insensitive on demand?
Followup May 11, 2007 - 11am Central time zone:
that is decided when you create the index, if you use the default, it is all folded to a consistent case in the supporting data structures (eg; the case is "lost")

May 11, 2007 - 1pm Central time zone
Reviewer: A reader
What then is the best way to handle the following situation?
SELECT ... WHERE CONTAINS(col1, 'abc') > 0
and
-- exact match
SELECT ... WHERE col1 = 'aBc'
Followup May 11, 2007 - 3pm Central time zone:
what you just did?
however, if you are using 10g, and you really have a "single word" in there, then you can use case insensitive session settings.
ops$tkyte%ORA10GR2> create table t ( data varchar2(20) );
Table created.
ops$tkyte%ORA10GR2> insert into t values ( 'Hello' );
1 row created.
ops$tkyte%ORA10GR2> insert into t values ( 'HeLlO' );
1 row created.
ops$tkyte%ORA10GR2> insert into t values ( 'HELLO' );
1 row created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create index t_idx_ci on t( nlssort( data, 'NLS_SORT=BINARY_CI' ) );
Index created.
ops$tkyte%ORA10GR2> create index t_idx on t( data );
Index created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2>ops$tkyte%ORA10GR2> variable x varchar2(25)
ops$tkyte%ORA10GR2> exec :x := 'Hello';
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> set autotrace on explain
ops$tkyte%ORA10GR2> select /*+ first_rows */ * from t where data = :x;
DATA
--------------------
Hello
Execution Plan
----------------------------------------------------------
Plan hash value: 2946670127
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T_IDX | 1 | 12 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DATA"=:X)
Note
-----
- dynamic sampling used for this statement
ops$tkyte%ORA10GR2> alter session set nls_comp=ansi;
Session altered.
ops$tkyte%ORA10GR2> alter session set nls_sort=binary_ci;
Session altered.
ops$tkyte%ORA10GR2> select /*+ first_rows */ * from t where data = :x;
DATA
--------------------
Hello
HeLlO
HELLO
Execution Plan
----------------------------------------------------------
Plan hash value: 164467589
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 12 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX_CI | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(NLSSORT("DATA",'nls_sort=''BINARY_CI''')=NLSSORT(:X,'nls_sort=''BI
NARY_CI'''))
Note
-----
- dynamic sampling used for this statement

May 12, 2007 - 12pm Central time zone
Reviewer: A reader
So when I execute a case sensitive query, I turn off the setting, and turn it back on when I execute a case insensitive query? Would this work in an application that uses connection pooling?
Also would this work well if I have a case insensitive query that has wildcard at both ends of the predicate?
select /*+ first_rows */ * from t where data = '%' || :x || '%';
Followup May 14, 2007 - 1pm Central time zone:
if you turn it on and off - sure it would work in a connection pool, you would just need to always set it to what you wanted.
if you use LINGUISTIC comparison semantics, like will work (you meant like I think...)
ops$tkyte%ORA10GR2> alter session set nls_comp=LINGUISTIC ;
Session altered.
ops$tkyte%ORA10GR2> alter session set nls_sort=binary_ci;
Session altered.
ops$tkyte%ORA10GR2> select * from t where data like '%'||:x||'%';
DATA
--------------------
Hello
HeLlO
HELLO
ops$tkyte%ORA10GR2> select * from t where data = :x;
DATA
--------------------
Hello
HeLlO
HELLO

May 14, 2007 - 2pm Central time zone
Reviewer: A reader
If my application needs to support all the following operators, some case sensitive, some case insensitive, would Oracle Text index be the best solution since the Text index supports both case insensitive and wildcard searches very well?
UPPER (<column>) LIKE '%ABC%'
UPPER(<column>) NOT LIKE '%ABC%'
<column> = 'abc'
<column> <> 'abc'
UPPER(<column>) = 'ABC'
UPPER(<column>) LIKE 'ABC%'
UPPER(<column>) LIKE '%ABC'
UPPER(<column>) IN ('ABC', 'DEF', 'XYZ')
UPPER(<column>) NOT IN ('ABC', 'DEF')
Oracle 9i: - Case Insensitive Query problem
May 22, 2007 - 1am Central time zone
Reviewer: cPiyush from IND
Hi Tom,
I have read your followups on this topic.
I have certain constraints: -
1. I can not change my queries(so can't use UPPER(<col>)..)
2. This looks wonderful
alter session set nls_comp=ansi;
alter session set nls_sort=binary_ci;
But 9i doesn't support 'binary_ci' value.
3. I tried this: -
alter session set nls_comp=ansi;
alter session set nls_sort=GENERIC_BASELETTER;
But this doesn't work for LIKE operator.
Please tell me the best solution considering constraint#1.
Info: - I have to fire case-insensitive queries on table which contains more than 3,000,000 records. & has this structure:
create table tabName (sno number,
col1 varchar2(200),
col2 varchar2(200),
col3 varchar2(200));
Regards,
cPiyush.
Followup May 22, 2007 - 9am Central time zone:
upgrade to 10g.
or - use a view?
Oracle 9i: -CASE INSENSITIVITY
May 25, 2007 - 2am Central time zone
Reviewer: cPiyush from IND
Hmmm...
Even if I will use a view then I will have to change all my queries which are currently selecting from <table> & I will have to make them to select from <view>.
I think I will have to upgrade to 10g.
No other choice remains, as other options are making me more complex.
But I am thinking abt one thing that if setting
alter session set nls_comp=ansi;
alter session set nls_sort=GENERIC_BASELETTER;
works for 'equals to' to make case insensitive then why they didn't make it for 'like'(Basically this is also a 'itrative equals to').
Regards,
cPiyush.
What statistics should replace 'first_rows' hint?
May 8, 2008 - 7am Central time zone
Reviewer: A reader from England
I am using Oracle 10.2.0.1
I wanted to repeat your example, but using optimizer statistics rather than the 'first_rows' hint. I don't seem to have the statistics right, as the index isn't being used:
SQL> create table t ( data varchar2(20) );
Table created.
SQL> insert into t
2 select 'Current' from all_objects;
41052 rows created.
SQL>
SQL> insert into t
2 select 'Historical' from dual;
1 row created.
SQL>
SQL>
SQL> create index t_idx on
2 t( nlssort( data, 'NLS_SORT=BINARY_CI' ) );
Index created.
SQL>
SQL>
SQL>
SQL> set autotrace traceonly
SQL> alter session set nls_comp=ansi;
Session altered.
SQL> alter session set nls_sort=binary_ci;
Session altered.
SQL>
SQL> select * from t
2 where data = 'CURRENT';
41052 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 470836197
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 465 | 5580 | 18 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 465 | 5580 | 18 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 186 | | 57 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(NLSSORT("DATA",'nls_sort=''BINARY_CI''')=HEXTORAW('63757272656E
7400') )
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
44 recursive calls
0 db block gets
5738 consistent gets
117 physical reads
0 redo size
553170 bytes sent via SQL*Net to client
30477 bytes received via SQL*Net from client
2738 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
41052 rows processed
SQL>
SQL> select * from t
2 where data = 'HISTORICAL';
Execution Plan
----------------------------------------------------------
Plan hash value: 470836197
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 465 | 5580 | 18 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 465 | 5580 | 18 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 186 | | 57 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(NLSSORT("DATA",'nls_sort=''BINARY_CI''')=HEXTORAW('686973746F72
6963616C00') )
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
11 recursive calls
0 db block gets
80 consistent gets
0 physical reads
0 redo size
415 bytes sent via SQL*Net to client
381 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
<b>SQL> exec dbms_stats.gather_table_stats('compass',tabname=>'t',cascade=>true,method_opt=>'for
all columns size 2',estimate_percent=>null)</b>
PL/SQL procedure successfully completed.
SQL> select * from t
2 where data = 'CURRENT';
41052 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 41052 | 360K| 22 (14)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 41052 | 360K| 22 (14)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NLSSORT("DATA",'nls_sort=''BINARY_CI''')=HEXTORAW('6375727
2656E7400') )
Statistics
----------------------------------------------------------
8 recursive calls
0 db block gets
2823 consistent gets
0 physical reads
0 redo size
553170 bytes sent via SQL*Net to client
30477 bytes received via SQL*Net from client
2738 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
41052 rows processed
SQL>
SQL> select * from t
2 where data = 'HISTORICAL';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 22 (14)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 9 | 22 (14)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NLSSORT("DATA",'nls_sort=''BINARY_CI''')=HEXTORAW('6869737
46F726963616C00') )
Statistics
----------------------------------------------------------
8 recursive calls
0 db block gets
86 consistent gets
0 physical reads
0 redo size
415 bytes sent via SQL*Net to client
381 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
|