How to use Regex in Oracle SQL request - sql

I have this complex string in a database, which represents 4 elements separated by delimeters '|'
1944913|200010|157|4*
1944913|200085|157|1.22*
NOTE: both lines of strings exist in the same database row. There could be up to 10 lines of strings in a single cell
I want an oracle sql command that, given either 200010 or 200085, returns either the 1st or second element next to it, like:
Given 200010, returns 157 or returns 4*
Given 200085, returns 157 or returns 1.22
How would I go about doing that?

You can use regexp_substr and instr to get the required results:
select a.*,
CASE WHEN instr(text1,'200085')>0 then REGEXP_SUBSTR (substr(text1,instr(text1,'200085'),500),'[^,|]+', 1, 2)
ELSE NULL END as partA,
CASE WHEN instr(text1,'200085')>0 then REGEXP_SUBSTR (substr(text1,instr(text1,'200085'),500),'[^,|]+', 1, 3)
ELSE NULL END as partB
from tableA a
Simply replace '200085' with the string you are looking for and you should be good to go. Hope this helps.

You can split this into columns easily. So, I think something like this is pretty much what you want:
select regexp_substr(col, '[^|]+', 1, 2) as val_2,
regexp_substr(col, '[^|]+', 1, 3) as val_3,
regexp_substr(col, '[^|]+', 1, 4) as val_4
from t;

Related

regexp_substr strip text between first forward slash and second one

/abc/required_string/2/ should return abc with regexp_substr
SELECT REGEXP_SUBSTR ('/abc/blah/blah/', '/([a-zA-Z0-9]+)/', 1, 1, NULL, 1) first_val
from dual;
You might try the following:
SELECT TRIM('/' FROM REGEXP_SUBSTR(mycolumn, '^\/([^\/]+)'))
FROM mytable;
This regular expression will match the first occurrence of a pattern starting with / (I habitually escape /s in regular expressions, hence \/ which won't hurt anything) and including any non-/ characters that follow. If there are no such characters then it will return NULL.
Hope this helps.
You can search for /([^/]+)/, which says:
/ forward slash
( start of subexpression (usually called "group" in other languages)
[^/] any character other than forward slash
+ match the preceding expression one or more times
) end of subexpression
/ forward slash
You can use the 6th argument to regexp_substr to select a subexpression.
Here we pass 1 to match only the characters between the /s:
select regexp_substr(txt, '/([^/]+)/', 1, 1, null, 1)
from t1
See it working at SQL Fiddle.
Classic SUBSTR + INSTR offer a simple solution; I know you specified regular expressions, but - consider this too, might work better for a large data volume.
SQL> with test (col) as
2 (select '/abc/required_string/2/' from dual)
3 select substr(col, 2, instr(col, '/', 1, 2) - 2) result
4 from test;
RES
---
abc
SQL>
Here's another way to get the 2nd occurrence of a string of characters followed by a forward slash. It handles the problem if that element happens to be NULL as well. Always expect the unexpected!
Note: If you use the regex form of [^/]+, and that element is NULL it will return "required string" which is NOT what you expect! That form does NOT handle NULL elements. See here for more info: [https://stackoverflow.com/a/31464699/2543416]
with tbl(str) as (
select '/abc/required_string/2/' from dual union all
select '//required_string1/3/' from dual
)
select regexp_substr(str, '(.*?)(/)', 1, 2, null, 1)
from tbl;

Removal of first characters in a string oracle sql

It may be very simple question, but I have run out of ideas.
I would like to remove first 5 characters from string.
Example string will look like:
1Y40K100R
I would like to display only digits that are after '%K' which in this case should give me result of 100R.
Please note that number after 'K' can have different amount of digits. It can be 4 digit number or 2 digit number.
Just use substr():
select substr(col, 6)
This returns all characters starting at the sixth.
There are multiple ways to return all characters after the k. If you know the string has a k, then use instr():
select substr(col, instr(col, 'K') + 1)
You can use regexp_substr
select regexp_substr('1Y40K100R', '(K)(.*)', 1, 1, 'i', 2) from dual
A way without regexp:
select substr('1Y40K100R', instr('1Y40K100R', 'K') +1) from dual
This may appear not so elegant, but it usually performs better than the regexp way.

How to extract value between 2 slashes

I have a string like "1490/2334/5166400411000434" from which I need to derive value after second slash. I tried below logic
select REGEXP_SUBSTR('1490/2334/5166400411000434','[^/]+',1,3) from dual;
it is working fine. But when i dont have value between first and second slash it is returining blank.
For example my string is "1490//5166400411000434" and am trying
select REGEXP_SUBSTR('1490//5166400411000434','[^/]+',1,3) from dual;
it is returning blank. Please suggest me what i am missing.
If I understand well, you may need
regexp_substr(t, '(([^/]*/){2})([^/]*)', 1, 1, 'i', 3)
This handles the first 2 parts like 'xxx/' and then checks for a sequence of non / characters; the parameter 3 is used to get the 3rd matching subexpression, which is what you want.
For example:
with test(t) as (
select '1490/2334/5166400411000434' from dual union all
select '1490//5166400411000434' from dual union all
select '1490//5166400411000434/ramesh/3344' from dual
)
select t, regexp_substr(t, '(([^/]*/){2})([^/]*)', 1, 1, 'i', 3) as substr
from test
gives:
T SUBSTR
---------------------------------- ----------------------------------
1490/2334/5166400411000434 5166400411000434
1490//5166400411000434 5166400411000434
1490//5166400411000434/ramesh/3344 5166400411000434
You can REVERSE() your string and take the value before the first slash. And then reverse again to obtain the desired output.
select reverse(regexp_substr(reverse('1490//5166400411000434'), '[^/]+', 1, 1)) from dual;
It can also be done with basic substring and instr function:
select reverse(SUBSTR(reverse('1490//5166400411000434'), 0, INSTR(reverse('1490//5166400411000434'), '/')-1)) from dual;
Use other options in REGEXP_SUBSTR to match a pattren
select REGEXP_SUBSTR('1490//5166400411000434','(/\d*)/(\d+)',1,1,'x',2) from dual
Basically it is finding the pattren of two / including digits starting from 1 with 1 appearance and ignoring whitespaces ('x') then outputting 2nd subexpression that is in second expression within ()
... pattern,1,1,'x',subexp2)

Regexp_substr is not working as expected

So, I have a piece of simple SQL like:
select
REGEXP_SUBSTR (randomcol, '[^|]+', 1, 2)
||'|'|| REGEXP_SUBSTR (randomcol, '[^|]+', 1, 3)
||'|'|| REGEXP_SUBSTR (randomcol, '[^|]+', 1, 4)
from table1 where ADDTL_DETAIL_INFO is not null and module_key='01-07-2016 00:00:00/2212/ 1';
The idea is to get the pipe separated values present in the randomcol column where the value present is:
~custom|HELLO1||HELLO3
So I need the values like HELLO1,whitespace (as there is no value between the second pipe and the third pipe) and HELLO3.
But when I ran the above query it returns as:
HELLO1|HELLO3|
and the white space is gone. I need this white space to retain. So what am I doing wrong here?
Regex of the form '[^|]+' does not work with NULL list elements and should be avoided! See this post for more info: Split comma separated values to columns in Oracle
Use this form instead:
select regexp_substr('1,2,3,,5,6', '(.*?)(,|$)', 1, 5, NULL, 1) from dual;
Which can be read as "get the 1st remembered group of the 5th occurrence of the set of characters ending with a comma or the end of the line".
So for your 4th element, you would use this to preserve the NULL in element 3 (assuming you want to build it by separate elements and not just grab the string from the character after the first separator to the end):
...
REGEXP_SUBSTR (addtl_detail_info, '(.*?)(\||$)', 1, 2) ||
REGEXP_SUBSTR (addtl_detail_info, '(.*?)(\||$)', 1, 3) ||
REGEXP_SUBSTR (addtl_detail_info, '(.*?)(\||$)', 1, 4)
...
You know, this may be easier. Just grab everything after the first pipe:
SQL> select REGEXP_replace('~custom|HELLO1||HELLO3', '^.*?\|(.*)', '\1') result
from dual;
RESULT
--------------
HELLO1||HELLO3
SQL>
The parenthesis surround what you want to "remember" and the replace string references the 1st remembered group with "\1".

Split String by delimiter position using oracle SQL

I have a string and I would like to split that string by delimiter at a certain position.
For example, my String is F/P/O and the result I am looking for is:
Therefore, I would like to separate the string by the furthest delimiter.
Note: some of my strings are F/O also for which my SQL below works fine and returns desired result.
The SQL I wrote is as follows:
SELECT Substr('F/P/O', 1, Instr('F/P/O', '/') - 1) part1,
Substr('F/P/O', Instr('F/P/O', '/') + 1) part2
FROM dual
and the result is:
Why is this happening and how can I fix it?
Therefore, I would like to separate the string by the furthest delimiter.
I know this is an old question, but this is a simple requirement for which SUBSTR and INSTR would suffice. REGEXP are still slower and CPU intensive operations than the old subtsr and instr functions.
SQL> WITH DATA AS
2 ( SELECT 'F/P/O' str FROM dual
3 )
4 SELECT SUBSTR(str, 1, Instr(str, '/', -1, 1) -1) part1,
5 SUBSTR(str, Instr(str, '/', -1, 1) +1) part2
6 FROM DATA
7 /
PART1 PART2
----- -----
F/P O
As you said you want the furthest delimiter, it would mean the first delimiter from the reverse.
You approach was fine, but you were missing the start_position in INSTR. If the start_position is negative, the INSTR function counts back start_position number of characters from the end of string and then searches towards the beginning of string.
You want to use regexp_substr() for this. This should work for your example:
select regexp_substr(val, '[^/]+/[^/]+', 1, 1) as part1,
regexp_substr(val, '[^/]+$', 1, 1) as part2
from (select 'F/P/O' as val from dual) t
Here, by the way, is the SQL Fiddle.
Oops. I missed the part of the question where it says the last delimiter. For that, we can use regex_replace() for the first part:
select regexp_replace(val, '/[^/]+$', '', 1, 1) as part1,
regexp_substr(val, '[^/]+$', 1, 1) as part2
from (select 'F/P/O' as val from dual) t
And here is this corresponding SQL Fiddle.