I have written the following query:
SELECT TBSPACE FROM SYSCAT.TABLES WHERE TYPE='T' AND (TABNAME LIKE '%_ABS_%' OR TABNAME LIKE '%_ACCT_%')
This gives me a certain amount of results. Now the problem is that I have multiple TABNAME to select using the LIKE operator (~200). Is there an efficient way to write the query for the 200 values without repeating the TABNAME LIKE part (because there are 200 such values which would result in a really huge query) ?
(If it helps, I have stored all required TABNAME values in a table TS to retrieve from)
If you are just looking for substrings, you could use LOCATE. E.g.
WITH SS(S) AS (
VALUES
('_ABS_')
, ('_ACCT_')
)
SELECT DISTINCT
TABNAME
FROM
SYSCAT.TABLES, SS
WHERE
TYPE='T'
AND LOCATE(S,TABNAME) > 0
or if your substrings are in table CREATE TABLE TS(S VARCHAR(64))
SELECT DISTINCT
TABNAME
FROM
SYSCAT.TABLES, TS
WHERE
TYPE='T'
AND LOCATE(S,TABNAME) > 0
You could try REGEXP_LIKE. E.g.
SELECT DISTINCT
TABNAME
FROM
SYSCAT.TABLES
WHERE
TYPE='T'
AND REGEXP_LIKE(TABNAME,'.*_((ABS)|(ACCT))_.*')
Just in case.
Note, that the '_' character has special meaning in a pattern-expression of the LIKE predicate:
The underscore character (_) represents any single character.
The percent sign (%) represents a string of zero or more characters.
Any other character represents itself.
So, if you really need to find _ABS_ substring, you should use something like below.
You get both rows in the result, if you use the commented out pattern instead, which may not be desired.
with
pattern (str) as (values
'%\_ABS\_%'
--'%_ABS_%'
)
, tables (tabname) as (values
'A*ABS*A'
, 'A_ABS_A'
)
select tabname
from tables t
where exists (
select 1
from pattern p
where t.tabname like p.str escape '\'
);
I have the following query which returns 0 results which I know is wrong. However not sure what is off with my syntax.
select * from SJT_USER where SJT_USER_NAME in
( select USER_NAME from NON_MEMBER);
SJT_USER_NAME type NCHAR(255 CHAR)
USER_NAME type NVARCHAR2(255 CHAR)
I'm guessing I need to do some conversion from NVARCHAR2 to NCHAR.
Try a SQL Cast so you're comparing apples to apples. I'm not certain which DBMS you're using, but the syntax should be similar to this:
select * from SJT_USER where SJT_USER_NAME in ( select CAST(USER_NAME AS NVARCHAR2) from NON_MEMBER);
A CHAR or NCHAR is fixed length so it the SJT_USER_NAME is padded by spaces so it fills up the 255 chars. When comparing the two there are two options. You can either TRIM or use RPAD:
select * from SJT_USER where TRIM(SJT_USER_NAME) in ( select USER_NAME from NON_MEMBER);
or
select * from SJT_USER where TRIM(SJT_USER_NAME) in ( select RPAD(USER_NAME,255) from NON_MEMBER);
The later might be preferable if you have an index SJT_USER_NAME. IF performance is not concern I usually prefer to have a TRIM on both sides of the comparison just to be on the safe side.
SQL newbie here, but I can't find the solution to something that looks easy:
The following query does not seem to have a valid syntax (ORA-00904: invalid identifier), but its logic should be clear. How can I achieve this in a query that needs to be speedy?
SELECT * FROM table WHERE LEFT(column,4)="abcd"
For this purpose, you should use like rather than left(). First, Oracle doesn't support left() (you need substr() instead). Second, like can make use of indexes because the wildcard is not at the beginning of the string:
SELECT *
FROM table
WHERE column like 'abcd%';
Oracle and some other products have substr.
SELECT * FROM tablename WHERE substr(columnname, 1, 4) = 'abcd'
I.e. single quotes for string literals!
ANSI SQL has substring:
SELECT * FROM tablename WHERE substring(columnname from 1 for 4) = 'abcd'
And others have left:
SELECT * FROM tablename WHERE LEFT(columnname,4) = 'abcd'
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
)
I have 10,001 rows in my table, and all of the rows except one start with a number. I need to find this one row that doesn't start with a number, or even that doesn't contain a number.
So this is what I have:
Select col1 from table1 where col1 not like '?%'
Is this even close? I need to find the row that doesn't have a number...
Thanks!!
UPDATE: I am using a sqlite database
Use:
SELECT col1
FROM table1
WHERE SUBSTR(col1, 1, 1) NOT BETWEEN 0 AND 9
Reference:
core functions (incl SUBSTR)
LIKE
On Sql Server,
Select * From table
Where col1 Like '[^0-9]%'
EDIT: Don't know if there is an equivilent on SQLLIte,
but this will work...
Select * From table
Where col1 Not Like '0%'
And col1 Not Like '1%'
...
And col1 Not Like '9%'
There is a post in code project that allow you to use Regex with Ms SQL.
Hope this help.
The easiest way might be to just note that you're not using numbers; you're using strings that happen to have numbers in them. In this case, you can do
select * from table1 where col1 not between '0' and '9:';
(where the colon is the ASCII character after '9'; this way '9999999' won't be found).
It should be a lot less expensive than some of the other suggestions (e.g., checking the value of the first character).
#Dueber got me thinking, couldn't you just do this?
SELECT * FROM table1 WHERE col1 > '9'
Grab the first character, see if it's numeric.
SELECT *
FROM table1
WHERE ISNUMERIC(SUBSTRING(col1,1,1)) = 0
SUBSTRING
ISNUMERIC