Oracle DB: How can I write query ignoring case? - sql

As I had written in title, I have SQL query, run on Oracle DB, lets say:
SELECT * FROM TABLE WHERE TABLE.NAME Like 'IgNoReCaSe'
If I would like, that the query would return either "IGNORECASE", "ignorecase" or combinations of them, how can this be done?

Select * from table where upper(table.name) like upper('IgNoreCaSe');
Alternatively, substitute lower for upper.

Use ALTER SESSION statements to set comparison to case-insensitive:
alter session set NLS_COMP=LINGUISTIC;
alter session set NLS_SORT=BINARY_CI;
If you're still using version 10gR2, use the below statements. See this FAQ for details.
alter session set NLS_COMP=ANSI;
alter session set NLS_SORT=BINARY_CI;

You can use either lower or upper function on both sides of the where condition

You could also use Regular Expressions:
SELECT * FROM TABLE WHERE REGEXP_LIKE (TABLE.NAME,'IgNoReCaSe','i');

You can use the upper() function in your query, and to increase performance you can use a function-base index
CREATE INDEX upper_index_name ON table(upper(name))

You can convert both values to upper or lowercase using the upper or lower functions:
Select * from table where upper(table.name) like upper('IgNoreCaSe')
or
Select * from table where lower(table.name) like lower('IgNoreCaSe');

In version 12.2 and above, the simplest way to make the query case insensitive is this:
SELECT * FROM TABLE WHERE TABLE.NAME COLLATE BINARY_CI Like 'IgNoReCaSe'

...also do the conversion to upper or lower outside of the query:
tableName:= UPPER(someValue || '%');
...
Select * from table where upper(table.name) like tableName

Also don't forget the obvious, does the data in the tables need to have case? You could only insert rows already in lower case (or convert the existing DB rows to lower case) and be done with it right from the start.

Related

Is there any SQL query character limit while executing it by using the JDBC driver [duplicate]

I'm using the following code:
SELECT * FROM table
WHERE Col IN (123,123,222,....)
However, if I put more than ~3000 numbers in the IN clause, SQL throws an error.
Does anyone know if there's a size limit or anything similar?!!
Depending on the database engine you are using, there can be limits on the length of an instruction.
SQL Server has a very large limit:
http://msdn.microsoft.com/en-us/library/ms143432.aspx
ORACLE has a very easy to reach limit on the other side.
So, for large IN clauses, it's better to create a temp table, insert the values and do a JOIN. It works faster also.
There is a limit, but you can split your values into separate blocks of in()
Select *
From table
Where Col IN (123,123,222,....)
or Col IN (456,878,888,....)
Parameterize the query and pass the ids in using a Table Valued Parameter.
For example, define the following type:
CREATE TYPE IdTable AS TABLE (Id INT NOT NULL PRIMARY KEY)
Along with the following stored procedure:
CREATE PROCEDURE sp__Procedure_Name
#OrderIDs IdTable READONLY,
AS
SELECT *
FROM table
WHERE Col IN (SELECT Id FROM #OrderIDs)
Why not do a where IN a sub-select...
Pre-query into a temp table or something...
CREATE TABLE SomeTempTable AS
SELECT YourColumn
FROM SomeTable
WHERE UserPickedMultipleRecordsFromSomeListOrSomething
then...
SELECT * FROM OtherTable
WHERE YourColumn IN ( SELECT YourColumn FROM SomeTempTable )
Depending on your version, use a table valued parameter in 2008, or some approach described here:
Arrays and Lists in SQL Server 2005
For MS SQL 2016, passing ints into the in, it looks like it can handle close to 38,000 records.
select * from user where userId in (1,2,3,etc)
I solved this by simply using ranges
WHERE Col >= 123 AND Col <= 10000
then removed unwanted records in the specified range by looping in the application code. It worked well for me because I was looping the record anyway and ignoring couple of thousand records didn't make any difference.
Of course, this is not a universal solution but it could work for situation if most values within min and max are required.
You did not specify the database engine in question; in Oracle, an option is to use tuples like this:
SELECT * FROM table
WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)
This ugly hack only works in Oracle SQL, see https://asktom.oracle.com/pls/asktom/asktom.search?tag=limit-and-conversion-very-long-in-list-where-x-in#9538075800346844400
However, a much better option is to use stored procedures and pass the values as an array.
You can use tuples like this:
SELECT * FROM table
WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)
There are no restrictions on number of these. It compares pairs.

Case insensitive search without using a function in the where clause

Any way to make a case insensitive without using a function in the where clause?
Please specify the database you are talking about when/if you reply. I am aware that MySQL is already case insensitive by default. What about Oracle or MSSQL or HANA?
select * from mytable WHERE upper(fieldname) = 'VALUE'
collate SQL_Latin1_General_CP1_CS_AS.
Default Collation is SQL_Latin1_General_CP1_CI_AS which is case insensitive. And if we need to make it case sensitive, then adding COLLATE Latin1_General_CS_AS makes the search case sensitive.
Query
select * from [mytable]
where [fieldname] = 'VALUE' collate SQL_Latin1_General_CP1_CS_AS;
Find a demo here
Since your question is tagged Oracle, I will provide a solution which works in Oracle.
You can set these session parameters for case insensitive searching
SQL> alter session set NLS_COMP=ANSI;
SQL> alter session set NLS_SORT=BINARY_CI;
SQL> select 1 from DUAL where 'abc' = 'ABC';
1
----------
1
Read more at Linguistic Sorting and String Searching
as #mathguy points out,
ALTER SESSION SET NLS_COMP=LINGUISTIC;
is more common than using ANSI
Making the column upper (or lower) case as you are showing in order to compare it, is the standard way of making a case insensitive comparision. (UPPER and LOWER are functions defined in the SQL standard.)
If you don't want to apply a function on the column, then you can of course write a recursive query to generate all upper/lower case permutations of the value ('VALUE', 'vALUE', 'VaLUE', ..., 'value') and check whether your column value is in this set. Standard SQL provides the SUBSTRING function for accessing substrings (e.g. the nth letter) and CHAR_LENGTH for getting the string's length.
It depends on the DBMS you are using and its version to what extent the standard is supported. In Oracle for example it's SUBSTR instead of SUBSTRING and LENGTH instead of CHAR_LENGTH. MySQL on the other hand features both SUBSTRING and CHAR_LENGTH directly, but only supports recursive queries as of version 8.0.
this will work:
SELECT *
FROM mytable
WHERE REGEXP_LIKE (column_name, 'value', 'i');
Oracle 12c answer
select * from mytable WHERE fieldname='Value' collate binary_ci
SAP HANA does not seem to have a way other than using upper or lower.
SQL Server and MySQL do not distinguish between upper and lower case letters—they are case-insensitive by default.
One could use CONTAINS Function. For example, Microsoft SQL Server query:
SELECT *
FROM TableName
WHERE ColumnName LIKE 'Abc%'
Maybe written in SAP HANA as:
SELECT *
FROM TableName
WHERE CONTAINS(ColumnName,'Abc%');
https://help.sap.com/viewer/05c9edaee7fe4d28ab3627d0b1583df6/2021_01_QRC/en-US/b45ff4c0e9ab4ba7a9e18a2552adeb3d.html

what is the maximum value we can use with IN operator in sql [duplicate]

I'm using the following code:
SELECT * FROM table
WHERE Col IN (123,123,222,....)
However, if I put more than ~3000 numbers in the IN clause, SQL throws an error.
Does anyone know if there's a size limit or anything similar?!!
Depending on the database engine you are using, there can be limits on the length of an instruction.
SQL Server has a very large limit:
http://msdn.microsoft.com/en-us/library/ms143432.aspx
ORACLE has a very easy to reach limit on the other side.
So, for large IN clauses, it's better to create a temp table, insert the values and do a JOIN. It works faster also.
There is a limit, but you can split your values into separate blocks of in()
Select *
From table
Where Col IN (123,123,222,....)
or Col IN (456,878,888,....)
Parameterize the query and pass the ids in using a Table Valued Parameter.
For example, define the following type:
CREATE TYPE IdTable AS TABLE (Id INT NOT NULL PRIMARY KEY)
Along with the following stored procedure:
CREATE PROCEDURE sp__Procedure_Name
#OrderIDs IdTable READONLY,
AS
SELECT *
FROM table
WHERE Col IN (SELECT Id FROM #OrderIDs)
Why not do a where IN a sub-select...
Pre-query into a temp table or something...
CREATE TABLE SomeTempTable AS
SELECT YourColumn
FROM SomeTable
WHERE UserPickedMultipleRecordsFromSomeListOrSomething
then...
SELECT * FROM OtherTable
WHERE YourColumn IN ( SELECT YourColumn FROM SomeTempTable )
Depending on your version, use a table valued parameter in 2008, or some approach described here:
Arrays and Lists in SQL Server 2005
For MS SQL 2016, passing ints into the in, it looks like it can handle close to 38,000 records.
select * from user where userId in (1,2,3,etc)
I solved this by simply using ranges
WHERE Col >= 123 AND Col <= 10000
then removed unwanted records in the specified range by looping in the application code. It worked well for me because I was looping the record anyway and ignoring couple of thousand records didn't make any difference.
Of course, this is not a universal solution but it could work for situation if most values within min and max are required.
You did not specify the database engine in question; in Oracle, an option is to use tuples like this:
SELECT * FROM table
WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)
This ugly hack only works in Oracle SQL, see https://asktom.oracle.com/pls/asktom/asktom.search?tag=limit-and-conversion-very-long-in-list-where-x-in#9538075800346844400
However, a much better option is to use stored procedures and pass the values as an array.
You can use tuples like this:
SELECT * FROM table
WHERE (Col, 1) IN ((123,1),(123,1),(222,1),....)
There are no restrictions on number of these. It compares pairs.

sql dynamic replacement

My requirement is that I am searching a bunch of columns in a table using regex_like function: Below is an example:
SELECT *
FROM dsopi_person_addr_rule ADDR
WHERE regexp_like (UPPER(addr.src_address_line1),
'DEP|DPT$|ABT|DIP.|DIPART|AFDEL|AVDEL|AVD.|DIV|PGRD|PGP|PPG')
Now what I would like to do if I find a match I would like to take the value from src_address_line1 and put that in another column of of the same table. I know how to do this but can anyone recommend how to do this efficiently. I am open to using cursors.
You dont need cursor for this
UPDATE dsopi_person_addr_rule ADDR
SET new_col = addr.src_address_line1
WHERE regexp_like (UPPER(addr.src_address_line1),
'DEP|DPT$|ABT|DIP.|DIPART|AFDEL|AVDEL|AVD.|DIV|PGRD|PGP|PPG')
I'd take a look at the CONTAINSTABLE clause, but that would require enabling / creating FULLTEXT indexes.
http://msdn.microsoft.com/en-us/library/ms189760.aspx

Set a column equal to a value in Oracle SELECT

I want to Select a column and set it equal to 0. In SQL I just do this: SELECT Dealer_Fee = 0.
Do I have to use an update? When I try the same thing in Oracle I get "FROM keyword not found where expected."
I am not sure what do you want to do and in which SQL dialect the construction you mentioned works. If you just want to retrieve some value and place it in a named column in Oracle you have to use DUAL table. Try this:
SELECT 0 AS dealer_fee FROM dual;
On the other hand, if you ment T-SQL and placing a value into variable you need to use PL/SQL SELECT INTO clause, like that:
SELECT 0 INTO dealer_fee from dual;
If not try to explain in more detail what are you trying to achieve.
1) In Oracle you must specify FROM clause within SELECT, is not like MS sqlserver where you can omit a FROM clause.
2) If you want to update one specific value, you must use UPDATE clause instead SELECT.
hth
You should use the Update statement. Please visit this oracle reference which explains the Update statement in detail: Update Statement
Take a look at the reference for UPDATE in Oracle:
UPDATE <table_name>
SET <column_name> = <value>