select * from table_Name where name ="red"
I need to fetch both "red" and "RED".
For example: I need to use both upper and lower in same statement.
How can I do this?
You could use case insensitive parameter at session 'NLS_SORT=BINARY_CI'. There are two parameters at session level:
NLS_COMP
NLS_SORT
Let's see a demo:
Normal scenario:
SQL> with names as
(
select 'Vishnu' name from dual
)
-- Your query starts here
select * from names where name='vIsHnU';
no rows selected
Case insensitive approach:
SQL> alter session set nls_comp='LINGUISTIC';
Session altered
SQL> alter session set nls_sort='BINARY_CI';
Session altered
SQL> with names as
(
select 'Vishnu' name from dual
)
-- Your query starts here
select * from names where name='vIsHnU';
NAME
------
Vishnu
One more example:
SQL> with names as
(
select 'red' name from dual union all
select 'RED' from dual
)
-- Your query starts here
select * from names where name='rEd';
NAME
----
red
RED
To improve the performance, you could also create a case insensitive INDEX.
For example:
create index names_ci_indx on names(NLSSORT(name,'NLS_SORT=BINARY_CI'));
Now, there are ways to improve performance of above transaction. Please read Oracle – Case Insensitive Sorts & Compares
select * from table_Name where lower(name) ="red"
or
select * from table_Name where upper(name) ="RED"
This cannot use an index on name. It might be appropriate to create a function based index on the expression used.
Related
This question already has answers here:
PL/SQL - Use "List" Variable in Where In Clause
(3 answers)
How to load a large number of strings to match with oracle database?
(3 answers)
Closed 10 months ago.
There's a way to store a set of codes into a variable in Oracle SQL?
I have these codes and I'll need to use them in different parts of my query.
But I wouldn't repeat this list in many places in my SQL code.
'G31', 'G310', 'G311', 'G312', 'G318', 'G319', 'G239', 'G122', 'G710',
'B20', 'B22', 'B23', 'B24', 'G35', 'C811', 'G37', 'G375', 'K702', 'K741'
I would like to do something like this idea:
LIST <- ['G31', 'G310', 'G311', 'G312', 'G318', 'G319', 'G239', 'G122', 'G710',
'B20', 'B22', 'B23', 'B24', 'G35', 'C811', 'G37', 'G375', 'K702', 'K741']
SELECT * FROM TABLE_A where COLUMN IN [LIST];
SELECT * FROM TABLE_B where COLUMN IN [LIST];
A fancy approach is this
WITH CODE_VALUES AS
( SELECT DISTINCT COLUMN_VALUE AS CODE_VALUE
FROM TABLE (sys.dbms_debug_vc2coll ('G31',
'G310',
'G311',
'G312',
'G318',
'G319',
'G239',
'G122',
'G710',
'B20',
'B22',
'B23',
'B24',
'G35',
'C811',
'G37',
'G375',
'K702',
'K741'))
)
SELECT *
FROM CODE_VALUES -- + the rest of your query
You could do the same thing with successive union's against "dual" too
WITH CODE_VALUES AS
( SELECT 'ABC' AS code_value FROM dual UNION
SELECT 'CDE' AS code_value FROM dual
)
If this is going to get used across multiple operational queries it's probably best just to store them in a table.
Create a global temporary table once and add the desired values in the gtt and then use it in query using join.
Benifit of gtt is that you don't have to worry about data maintance. (Delete - insert). Data added in one session/transaction will be visible in that session/transaction only (based on type of gtt that you have created.
Create global temporary table gtt
(Col1 varchar2(10))
On commit preserve row; -- session specific
Insert into gtt
Select 'G31' from dual union all
Select 'G310' from dual union all
...
...
Select 'K741' from dual;
Now, you can use it anywhere in the same session as follows:
SELECT *
FROM TABLE_A a
Join gtt g on a.COLUMN = g.col1;
SELECT *
FROM TABLE_B b
Join gtt g on b.COLUMN = g.col1;
I have 10 records in a table. Out of these records, I need to perform the following 3 operations using a single Oracle query(the reason for saying single query is that this is part of an automation framework and I need to keep a single generic query)
Operation 1: get all the 10 records
Select * from table_name where col01 like ('%')
<<10 records fetched>>
Operation 2: get records that start with the string "Tivoli"
Select * from table_name where col01 like ('Tivoli%')
<<1 record fetched>>
Operation 3: get records that DOES NOT start with "Tivoli"
<<should give 9 records>>
I am Not able to write the query for operation 3 but I do not want to use a separate NOT LIKE clause as this would make me create a separate query altogether.
Then, you can use minus set operator :
Select * from table_name -- all records
minus
Select * from table_name where col01 like 'Tivoli%'
-- records for col01 column starts with Tivoli
If all types of Tivoli( such as TIVOLI.. or tIvOli or .. ) should be included case-insensitively, then you can consider the condition as
where lower(col01) like 'tivoli%'
You can use:
select *
from table_name
where col01 not like 'Tivoli%'
If col01 can be NULL, then you need to take that into account:
select *
from table_name
where col01 not like 'Tivoli%' or col01 is null;
Select * from table_name where not (col01 like ('Tivoli%') )
You are asking for a generic query that covers all three options. Use two variables for this and set them null when you don't want to use them:
Select *
from table_name
where (col01 like :must_match or :must_match is null)
and (col01 not like :must_not_match or col01 is null or :must_not_match is null);
Or, if you want to have your framework deal with match or no match, select all rows with a flag:
Select
t.*,
case when col01 like :pattern then 'match' else 'no match' end as is_match
from table_name t;
I want to find all insert, update , and merge lines in whole dba
what i tried:
SELECT owner, name, type,line,text
FROM dba_source where regexp_like(text,'into my_table')
union all
SELECT owner, name, type,line,text
FROM dba_source where regexp_like(text,'update my_table')
but nothing returns from my select function.
EDIT: The return must contain specific table. Return should not contain tables like "my_table_2" or "my_table_temp"
You are not using a very good method to search. You will not get any results, if the source is saved in the below way -
insert
into
any_table
Because there are multiple new lines, so your query from dba_source/all_source will fail.
A better way to find that is -
select * from dba_dependencies
where referenced_name = 'TABLE_NAME|SYNONYM_NAME'
and referenced_type = 'TABLE|SYNONYM'
Example,
suppose you have a PROCEDURE XYZ, which has the below construct
create or replace procedure xyz
begin
insert
into
any_table ....
end;
Then, if you run the below query
select * from dba_dependencies
where referenced_name = 'any_table'
and referenced_type = 'TABLE';
The result of the above query will give you 'XYZ' as a record.
As I mentioned in comments, one issue could be the case of the text. Another could be the number of white-space characters between the characters.
SELECT owner,
name,
type,
line,
text
FROM dba_source
WHERE REGEXP_LIKE(
text,
'(into|update)\s+table_name(\s|$)',
-- Match both conditions and any amount of white-space
'i' -- Case insensitive
)
You then need to deal with other case where:
The table identifier is on the next line from the INTO or UPDATE keyword;
The table identifier has a schema prefix SCHEMA_NAME.TABLE_NAME; or
The an identifier is quoted "TABLE_NAME" or "SCHEMA_NAME"."TABLE_NAME";
A combination of the above.
Which would give you an expression like:
SELECT owner,
name,
type,
line,
text
FROM dba_source
WHERE REGEXP_LIKE(
text,
'(into|update)\s+(("?)schema_name\3\.)?("?)table_name\4(\s|$)',
-- Match both conditions, schema, quotes and any amount of white-space
'i' -- Case insensitive
)
You could also use LAG or LEAD to look for statements spread across lines.
There are several things to consider:
there may be space between the keyword INSERT and the table name
there may be a schema name preceding the table name (my_schema.my_table)
the table name may be in upper or lower case or a mix of them
excluding my_table_xxx for a search on my_table, as you already mentioned
Here is a query for this:
SELECT owner, name, type, line, text
FROM dba_source
WHERE regexp_like(text, '(update|into)[[:space:]]+my_table($|\s|\W)', 'i')
OR regexp_like(text, '(update|into)[[:space:]]+[[:alpha:]]+\.my_table($|\s|\W)', 'i');
However, this still doesn't cover the case where you have INSERT in one line and the table name in the next.
Try this:-
SELECT owner, name, type,line,text
FROM dba_source where regexp_like(UPPER(text),'INTO YOUR_TABLE_NAME')
union all
SELECT owner, name, type,line,text
FROM dba_source where regexp_like(UPPER(text),'UPDATE YOUR_TABLE_NAME');
How can I put with regex, schema name table, for query select?
Query doesn't have fixed size.
Example:
select * from t1 union select * from t2
Result:
select * from schema1.t1 union select * from schema1.t2
Thanks!
(1) If you are using it in a code, maybe you can do a search and replace at front end as Luk suggested.
(2) Alternatively, in your current session you can set default schema as schema1 so your query would work without schema name. But it would depend on your database name.
Like in Oracle you can do
ALTER SESSION SET CURRENT_SCHEMA=schema1
Now select * from t1 would effectively mean select * from schema1.t1.
You can search how to set default schema in <your database> in google and you would get syntax for other databases as well.
I know I can write a query that will return all rows that contain any number of values in a given column, like so:
Select * from tbl where my_col in (val1, val2, val3,... valn)
but if val1, for example, can appear anywhere in my_col, which has datatype varchar(300), I might instead write:
select * from tbl where my_col LIKE '%val1%'
Is there a way of combing these two techniques. I need to search for some 30 possible values that may appear anywhere in the free-form text of the column.
Combining these two statements in the following ways does not seem to work:
select * from tbl where my_col LIKE ('%val1%', '%val2%', 'val3%',....)
select * from tbl where my_col in ('%val1%', '%val2%', 'val3%',....)
What would be useful here would be a LIKE ANY predicate as is available in PostgreSQL
SELECT *
FROM tbl
WHERE my_col LIKE ANY (ARRAY['%val1%', '%val2%', '%val3%', ...])
Unfortunately, that syntax is not available in Oracle. You can expand the quantified comparison predicate using OR, however:
SELECT *
FROM tbl
WHERE my_col LIKE '%val1%' OR my_col LIKE '%val2%' OR my_col LIKE '%val3%', ...
Or alternatively, create a semi join using an EXISTS predicate and an auxiliary array data structure (see this question for details):
SELECT *
FROM tbl t
WHERE EXISTS (
SELECT 1
-- Alternatively, store those values in a temp table:
FROM TABLE (sys.ora_mining_varchar2_nt('%val1%', '%val2%', '%val3%'/*, ...*/))
WHERE t.my_col LIKE column_value
)
For true full-text search, you might want to look at Oracle Text: http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html
A REGEXP_LIKE will do a case-insensitive regexp search.
select * from Users where Regexp_Like (User_Name, 'karl|anders|leif','i')
This will be executed as a full table scan - just as the LIKE or solution, so the performance will be really bad if the table is not small. If it's not used often at all, it might be ok.
If you need some kind of performance, you will need Oracle Text (or some external indexer).
To get substring indexing with Oracle Text you will need a CONTEXT index. It's a bit involved as it's made for indexing large documents and text using a lot of smarts. If you have particular needs, such as substring searches in numbers and all words (including "the" "an" "a", spaces, etc) , you need to create custom lexers to remove some of the smart stuff...
If you insert a lot of data, Oracle Text will not make things faster, especially if you need the index to be updated within the transactions and not periodically.
No, you cannot do this. The values in the IN clause must be exact matches. You could modify the select thusly:
SELECT *
FROM tbl
WHERE my_col LIKE %val1%
OR my_col LIKE %val2%
OR my_col LIKE %val3%
...
If the val1, val2, val3... are similar enough, you might be able to use regular expressions in the REGEXP_LIKE operator.
Yes, you can use this query (Instead of 'Specialist' and 'Developer', type any strings you want separated by comma and change employees table with your table)
SELECT * FROM employees em
WHERE EXISTS (select 1 from table(sys.dbms_debug_vc2coll('Specialist', 'Developer')) mt
where em.job like ('%' || mt.column_value || '%'));
Why my query is better than the accepted answer: You don't need a CREATE TABLE permission to run it. This can be executed with just SELECT permissions.
In Oracle you can use regexp_like as follows:
select *
from table_name
where regexp_like (name, '^(value-1|value-2|value-3....)');
The caret (^) operator to indicate a beginning-of-line character &
The pipe (|) operator to indicate OR operation.
This one is pretty fast :
select * from listofvalue l
inner join tbl on tbl.mycol like '%' || l.value || '%'
Just to add on #Lukas Eder answer.
An improvement to avoid creating tables and inserting values
(we could use select from dual and unpivot to achieve the same result "on the fly"):
with all_likes as
(select * from
(select '%val1%' like_1, '%val2%' like_2, '%val3%' like_3, '%val4%' as like_4, '%val5%' as like_5 from dual)
unpivot (
united_columns for subquery_column in ("LIKE_1", "LIKE_2", "LIKE_3", "LIKE_4", "LIKE_5"))
)
select * from tbl
where exists (select 1 from all_likes where tbl.my_col like all_likes.united_columns)
I prefer this
WHERE CASE WHEN my_col LIKE '%val1%' THEN 1
WHEN my_col LIKE '%val2%' THEN 1
WHEN my_col LIKE '%val3%' THEN 1
ELSE 0
END = 1
I'm not saying it's optimal but it works and it's easily understood. Most of my queries are adhoc used once so performance is generally not an issue for me.
select * from tbl
where exists (select 1 from all_likes where all_likes.value = substr(tbl.my_col,0, length(tbl.my_col)))
You can put your values in ODCIVARCHAR2LIST and then join it as a regular table.
select tabl1.* FROM tabl1 LEFT JOIN
(select column_value txt from table(sys.ODCIVARCHAR2LIST
('%val1%','%val2%','%val3%')
)) Vals ON tabl1.column LIKE Vals.txt WHERE Vals.txt IS NOT NULL
You don't need a collection type as mentioned in https://stackoverflow.com/a/6074261/802058. Just use an subquery:
SELECT *
FROM tbl t
WHERE EXISTS (
SELECT 1
FROM (
SELECT 'val1%' AS val FROM dual
UNION ALL
SELECT 'val2%' AS val FROM dual
-- ...
-- or simply use an subquery here
)
WHERE t.my_col LIKE val
)