Using REGXP_LIKE within queryExecute() - sql

I'm looking to modify an existing query to use REGEXP_LIKE but falling foul of some syntax I'm not understanding properly. We've currently a CF query into an Oracle DB using the following:
result = QueryExecute("
SELECT paramOne, paramTwo FROM someTable WHERE fieldOne = :PUBLISHER
", {PUBLISHER=publisherId}, {datasource="someDB"});
which works. However, I want to modify the underlying query to be:
result = QueryExecute("
SELECT paramOne, paramTwo FROM someTable WHERE REGEXP_LIKE(fieldOne, '(^|,)(:PUBLISHER)($|,)', 'i')
", {PUBLISHER=publisherId}, {datasource="someDB"});
but it's not delivering the expected results. A few things I've noted as I try to debug...
The underlying query(without using a variable) works and has been verified in Oracle SQL
If I go to the source code and replace :PUBLISHER with a 'hard coded' value the things work as expected.
I've tried escaping the ':' but that's not the answer.
I fell there's something I'm not understanding about passing variables into a REGEX expression within queryExecute(), so would appreciate any thoughts.
Any input gratefully received,
Phil

SQL>
with t (fieldOne) as (
select 'abc, def' from dual union all
select 'def cba' from dual union all
select ':publisher' from dual
)
select * from t where REGEXP_LIKE(fieldOne, '(^|,)(:PUBLISHER)($|,)', 'i');
FIELDONE
----------
:publisher
SQL>
with t (fieldOne) as (
select 'abc, def' from dual union all
select 'def cba' from dual union all
select ':publisher' from dual
)
select * from t where REGEXP_LIKE(fieldOne, '(^|,)(' || :PUBLISHER || ')($|,)', 'i');
FIELDONE
----------
abc, def

Related

Find value that is not a number or a predefined string

I have to test a column of a sql table for invalid values and for NULL.
Valid values are: Any number and the string 'n.v.' (with and without the dots and in every possible combination as listed in my sql command)
So far, I've tried this:
select count(*)
from table1
where column1 is null
or not REGEXP_LIKE(column1, '^[0-9,nv,Nv,nV,NV,n.v,N.v,n.V,N.V]+$');
The regular expression also matches the single character values 'n','N','v','V' (with and without a following dot). This shouldn't be the case, because I only want the exact character combinations as written in the sql command to be matched. I guess the problem has to do with using REGEXP_LIKE. Any ideas?
I guess this regexp will work:
NOT REGEXP_LIKE(column1, '^([0-9]+|n\.?v\.?)$', 'i')
Note that , is not a separator, . means any character, \. means the dot character itself and 'i' flag could be used to ignore case instead of hard coding all combinations of upper and lower case characters.
No need to use regexp (performance will increase by large data) - plain old TRANSLATE is good enough for your validation.
Note that the first translate(column1,'x0123456789','x') remove all numeric charcters from the string, so if you end with nullthe string is OK.
The second translate(lower(column1),'x.','x') removes all dots from the lowered string so you expect the result nv.
To avoid cases as n.....v.... you also limit the string length.
select
column1,
case when
translate(column1,'x0123456789','x') is null or /* numeric string */
translate(lower(column1),'x.','x') = 'nv' and length(column1) <= 4 then 'OK'
end as status
from table1
COLUMN1 STATUS
--------- ------
1010101 OK
1012828n
1012828nv
n.....v....
n.V OK
Test data
create table table1 as
select '1010101' column1 from dual union all -- OK numbers
select '1012828n' from dual union all -- invalid
select '1012828nv' from dual union all -- invalid
select 'n.....v....' from dual union all -- invalid
select 'n.V' from dual; -- OK nv
You can use:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR LOWER(column1) IN ('nv', 'n.v', 'nv.', 'n.v.');
Which, for the sample data:
CREATE TABLE table1 (column1) AS
SELECT '12345' FROM DUAL UNION ALL
SELECT 'nv' FROM DUAL UNION ALL
SELECT 'NV' FROM DUAL UNION ALL
SELECT 'nV' FROM DUAL UNION ALL
SELECT 'n.V.' FROM DUAL UNION ALL
SELECT '...................n.V.....................' FROM DUAL UNION ALL
SELECT '..nV' FROM DUAL UNION ALL
SELECT 'n..V' FROM DUAL UNION ALL
SELECT 'nV..' FROM DUAL UNION ALL
SELECT 'xyz' FROM DUAL UNION ALL
SELECT '123nv' FROM DUAL;
Outputs:
COUNT(*)
5
or, if you want any quantity of . then:
select count(*)
from table1
WHERE TRANSLATE(column1, ' 0123456789', ' ') IS NULL
OR REPLACE(LOWER(column1), '.') = 'nv';
Which outputs:
COUNT(*)
9
db<>fiddle here

Extracting substring in Oracle

Let's say I have three rows with value as
1 121/2808B|:6081
2 OD308B|:6081_1:
3 008312100001200|:6081_1
I want to display value only until B but want to exclude everything after B. So as you can see in above data:
from 121/2808B|:6081 I want only 121/2808B
from OD308B|:6081_1: only OD308B
from 008312100001200|:6081_1 only 008312100001200.
Thanks for the Help.
Try this: regexp_substr('<Your_string>','[^B]+')
SELECT
REGEXP_SUBSTR('121/2808B|:6081', '[^B]+')
FROM
DUAL;
REGEXP_S
--------
121/2808
SELECT
REGEXP_SUBSTR('OD308B|:6081_1:', '[^B]+')
FROM
DUAL;
REGEX
-----
OD308
SELECT
REGEXP_SUBSTR('008312100001200.', '[^B]+')
FROM
DUAL;
REGEXP_SUBSTR('0
----------------
008312100001200.
db<>fiddle demo
Cheers!!
You could try using SUBSTR() and INSTR()
select SUBSTR('121/2808B|:6081',1,INSTR('121/2808B|:6081','B', 1, 1) -1)
from DUAL
I think you forgot to mention that you wanted to use | as a field separator, but I deduced this from the expected result from the third string. As such the following should give you what you want:
WITH cteData AS (SELECT 1 AS ID, '121/2808B|:6081' AS STRING FROM DUAL UNION ALL
SELECT 2, 'OD308B|:6081_1:' FROM DUAL UNION ALL
SELECT 3, '008312100001200|:6081_1' FROM DUAL)
SELECT ID, STRING, SUBSTR(STRING, 1, CASE
WHEN INSTR(STRING, 'B') = 0 THEN INSTR(STRING, '|')-1
ELSE INSTR(STRING, 'B')-1
END) AS UP_TO_B
FROM cteData;
dbfiddle here
Assuming Bob Jarvis is correct in the assumption that "|" is also a delimiter (as seems likely) try:
-- define test data
with test as
( select '121/2808B|:6081' stg from dual union all
select 'OD308B|:6081_1:' from dual union all
select '008312100001200|:6081_1' from dual
)
-- execute extract
select regexp_substr(stg , '[^B|]+') val
from test ;

How to cut everything after a specific character, but in case string doesn't contain it do nothing?

Let's say i have following data:
fjflka, kdjf
ssssllkjf fkdsjl
skfjjsld, kjl
jdkfjlj, ksd
lkjlkj hjk
I want to cut out everything after ',' but in case the string doesn't contain this character, it wont do anything, if i use substr and cut everything after ',' the string which doesn't contain this character shows as null. How do i achieve this? Im using oracle 11g.
This should work. Simply use regexp_substr
with t_view as (
select 'fjflka, kdjf' as text from dual union
select 'ssssllkjf fkdsjl' from dual union
select 'skfjjsld, kjl' from dual union
select 'jdkfjlj, ksd' from dual union
select 'lkjlkj hjk' from dual
)
select text,regexp_substr(text,'[^,]+',1,1) from t_view;
Assuming your table :
SQL> desc mytable
s varchar2(100)
you may use:
select decode(instr(s,','),0,s,substr(s,1,instr(s,',')-1)) from mytable;
demo
Well the below query works as per your requirement.
with mytable as
(select 'aaasfasf wqwe' s from dual
union all
select 'aaasfasf, wqwe' s from dual)
select s,substr(s||',',1,instr(s||',',',')-1) from mytable;

Select query does not work

Query:
select *
from etm
where emp_id LIKE '009090%'
AND directnumber LIKE '111 123 12345x 67%'
AND cellnumber LIKE '123456789%'
AND phone LIKE '111 123 12345x 67';
database: oracle 11g
Select query doesn't return any records when the LIKE operator has small X character (12345x) in it.
When I replace it with any other character (small/capital) it works ((12345Y)), but replacing it with the small x also does not work.
I cannot modify the query, is there anything can be done at database level while inserting the data?
we are importing data in bulk.
I can't see an issue - here's a test case to demonstrate:
with sample_data as (select '123x 456' str from dual union all
select '123 456' str from dual union all
select '123x' str from dual union all
select 'abcx 93s' str from dual)
select *
from sample_data
where str like '123x%';
STR
--------
123x 456
123x
So, you can see my search has pulled back rows where the str column starts with 123x.
However, if I search for rows starting with 123y then no rows are returned:
with sample_data as (select '123x 456' str from dual union all
select '123 456' str from dual union all
select '123x' str from dual union all
select 'abcx 93s' str from dual)
select *
from sample_data
where str like '123y%';
no rows selected.
since there are no rows where the str column starts with 123y.
Is it a similar case with your data, where there aren't any rows that match all the filter conditions when you have an x in one or more of the like conditions?
I haven't verified this query but it should work.
select *
from etm
where emp_id LIKE '009090%'
AND (directnumber LIKE '111%' or directnumber LIKE '123%' .....)
AND cellnumber LIKE '123456789%'
AND (phone LIKE '111' or phone LIKE '123' .......);
Reference :
https://community.oracle.com/thread/1096523?start=0&tstart=0

Oracle regexp to ignore repeating characters

I've a string like:
hheelllloo wwoorrlldd !!
that should return hello world!
and my try for the above is
SELECT regexp_substr('hheelllloo wwoorrlldd !!', '.', LEVEL*2-1)l_val
FROM dual
CONNECT BY LEVEL <= LENGTH('hheelllloo wwoorrlldd !!')/2;
But its not the way i needed and the logic is not correctly used.
I've also tried using '(\w)\1'
My expected result in a sample data:
WITH t AS
( SELECT 'hheelllloo wwoorrlldd!!' AS word FROM dual
UNION
SELECT 'hellow world!' FROM dual
UNION
SELECT 'ootthheerrss' FROM dual
UNION
SELECT 'ootthheeerrss' FROM dual
)
SELECT * FROM t;
output should looks like:
hello world! --expression applied
hellow world! -- not needed for non-repeated characters
others --expression applied
otheers --applied and extra `e` considered as non-repeated.
Can I make the whole in a single query., or the first one?
Thanks in advance and this is only for my practice and to know different logic.
You can use regexp_replace() regular expression function with back reference:
SQL> WITH t1(col) AS (
2 select 'hheelllloo wwoorrlldd!!' from dual union all
3 select 'hellow world!' from dual union all
4 select 'ootthheerrss' from dual union all
5 select 'ootthheeerrss' from dual
6 )
7 select regexp_replace(col, '(.)\1', '\1') as res
8 from t1
9 ;
RES
--------------
hello world!
helow world!
others
otheers
And
select regexp_replace('A;A;B;B', '(.)\1', '\1')
from `dual`
Output:
A;B ????????
I have this answer.