If you don't want to have to maintain another column but still want to be able to use the index (upper kills the index), you can do it like Oracle Forms does it internally when you use case insensitive query.
What you have to do is compare all 4 possible combinations of the two first letters of your search to the database column, before you do your upper part. That way the number of rows will be minimized considerably before the upper part comes along. If the varians of your data is OK, which means that not all of your records starts with the same two letters, the upper part will only have to do a scan on maybe 1 percent of your records.
Here's an example:
Let's say "KKM" is the table you want to do your search in, "a" is the column you want to search and "con" is the constant you want to search for:
select a
from kkm
where (a like upper(substr(con,1,2))||'%'
or a like upper(substr(con,1,1))||lower(substr(con,2,1))||'%'
or a like lower(substr(con,1,1))||upper(substr(con,2,1))||'%'
or a like lower(substr(con,1,2))||'%')
and upper(a)=upper(con);
I've done case insencitive searches in tables with millions of records and gotten my answer back within miliseconds, using this technic.
Regards
Klaus Mogensen