extract the value between two parameters oracle - sql

I am trying to extract the string 01-DEC-17 from '123|01-DEC-17|-123'. But I am not getting desired output:
SELECT SUBSTR('123|01-DEC-17|-123', INSTR('123|01-DEC-17|-123','|', 1)+1, INSTR('123|01-DEC-17|-123', '|',-1)+1)
FROM DUAL;
Output is coming as 01-DEC-17|-123. but the desired output is 01-DEC-17. Any help would be appreciated

Use regexp_substr(). Here is one method:
select trim(both '|' from regexp_substr(col, '|[^|]+|'))
Or, if you know that the positions are fixed, you can just use substr():
select substr(col, 5, 9)

Try this:
with t (col)
as (
select '123|01-DEC-17|-123'
from dual
)
select substr(
col,
instr(col, '|') + 1,
instr(col, '|', 1, 2) - instr(col, '|') - 1
)
from t;
instr(col, '|') - Location of first occurrence of |
instr(col, '|', 1, 2) - Location of second occurrence of |
For substr(column, start_position, length), We need length of subtring as third parameter to substr, so,
instr(col, '|', 1, 2) - instr(col, '|') - 1 will give us the required length.

Related

Regex values after special character with empty values

I am struggle with regex to split spring into columns in Oracle database.
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '[^: ]+', 1, 4)) from dual;
I need to obtain 4th value from that string as a column value, sometimes values at position 2,3 are empty and my query doesn't work. I am trying to figure out what regex will work
You can use
select (REGEXP_SUBSTR(replace('1:::9999', ' ',''), '([^: ]*)(:|$)', 1, 4, 'i', 1)) from dual;
Here, the ([^: ]*)(:|$) matches
([^: ]*) - Group 1: any zero or more chars other than : and space
(:|$) - Group 2, either : or end of string.
You do not need a (slower) regex for this task, use simple substr/instr functions:
with input_(val) as (
select '1:::9999' from dual
union all
select '1:2::' from dual
union all
select '1:2::3:5' from dual
)
, replaced as (
select input_.*, replace(val, ' ', '') as val_replaced
from input_
)
select
val,
substr(
val_replaced,
/*Locate the first occurrence of a colon and get a substring ...*/
instr(val_replaced, ':', 1, 3) + 1,
/*.. until the end, if the next colon is absent, or until the next colon*/
nvl(nullif(instr(val_replaced, ':', 1, 4), 0), length(val_replaced) + 1) - instr(val_replaced, ':', 1, 3) - 1
) as col
from replaced
VAL
COL
1:::9999
9999
1:2::
null
1:2::3:5
3
fiddle with performance difference.

How do I get substring after a character when the occurance of the character keeps changing

Example
123\.456.578.910.ABC
123\.456.578.910
Expected result
123\.456.578
123\.456.578
For the both the inputs I should get only the first 3
I tried the regexp and substring and instr but I’m not getting the results
We can use REGEXP_SUBSTR here with a capture group:
SELECT REGEXP_SUBSTR(col, '^(\d+(\.\d+)*)', 1, 1, NULL, 1)
FROM yourTable;
Demo
Traditional, substr + instr combination is another option:
Sample data:
SQL> with test (col) as
2 (select '123\.456.578.910.ABC' from dual union all
3 select '123\.456.578.910' from dual
4 )
Query begins here:
5 select col,
6 substr(col, 1, instr(col, '.', 1, 3) - 1) result
7 from test;
COL RESULT
-------------------- --------------------
123\.456.578.910.ABC 123\.456.578
123\.456.578.910 123\.456.578
SQL>
If you value will always have at least 3 . characters then you can use:
SELECT value,
SUBSTR(value, 1, INSTR(value, '.', 1, 3) - 1) AS expected
FROM table_name;
If it may have fewer and you want the entire string in those cases then:
SELECT value,
CASE INSTR(value, '.', 1, 3)
WHEN 0
THEN value
ELSE SUBSTR(value, 1, INSTR(value, '.', 1, 3) - 1)
END AS expected
FROM table_name;
Which, for your sample data:
CREATE TABLE table_name (value) AS
SELECT '123\.456.578.910.ABC' FROM DUAL UNION ALL
SELECT '123\.456.578.910' FROM DUAL;
Both outputs:
VALUE
EXPECTED
123.456.578.910.ABC
123.456.578
123.456.578.910
123.456.578
db<>fiddle here

REGEXP_SUBSTR SPLIT Function

i want to split this into 2019/GA/0000104
select REGEXP_SUBSTR('2019/0000015,2019/GA/0000104,2cdb376e-2966-4f24-9063-f4c6f31a6f35', '[^,]+')
from dual;
Output = 2019/GA/0000104
can u guys help?
It seems that you want to extract the second substring. If that's so, then you could use
regexp_substr (result), or
substr + inenter code herestr combination (result2)
SQL> with test (col) as
2 (select '2019/0000015,2019/GA/0000104,2cdb376e-2966-4f24-9063-f4c6f31a6f35' from dual)
3 select regexp_substr(col, '[^,]+', 1, 2) result,
4 --
5 substr(col, instr(col, ',', 1, 1) + 1,
6 instr(col, ',', 1, 2) - instr(col, ',', 1, 1) - 1
7 ) result2
8 from test;
RESULT RESULT2
--------------- ---------------
2019/GA/0000104 2019/GA/0000104
SQL>
Try using REGEXP_SUBSTR with a capture group:
SELECT
REGEXP_SUBSTR(input, ',(.*),', 1, 1, NULL, 1)
FROM yourTable;
Demo
This form of the regex returns the second occurrence of a string of characters that are followed by a comma or the end of the line. It returns the correct element if the first one should ever be NULL.
with tbl(str) as (
select '2019/0000015,2019/GA/0000104,2cdb376e-2966-4f24-9063-f4c6f31a6f35' from dual
)
select regexp_substr(str, '(.*?)(,|$)', 1, 2, NULL, 1)
from tbl;

Oracle regex substring

I am trying to get the value between two semi colons.
select (REGEXP_SUBSTR(col,'[^:]+',1,2,null)) from test
These are the rows I am dealing with:
1236:10:EXEC
1236::EXEC
In my result set, I want to get:
10
<null>
The query above returns:
10
EXEC
You can avoid regexp for this; for example:
select substr(col, instr(col, ':') +1, instr(col, ':', 1, 2) - instr(col, ':') -1)
from test
How it works:
select instr(col, ':') as firstColon,
instr(col, ':', 1, 2) as secondColon,
instr(col, ':', 1, 2) - instr(col, ':') -1 as lengthOfResultingString,
substr(col, instr(col, ':') +1, instr(col, ':', 1, 2) - instr(col, ':') -1) as result
from test
gives:
FIRSTCOLON SECONDCOLON LENGTHOFRESULTINGSTRING RESULT
---------- ----------- ----------------------- ------------
5 8 2 10
5 6 0
This assumes that you always have at least two colon characters in the string.
With regexp, in a slower, but more compact way, you could use:
regexp_substr(col, ':([^:]*):', 1, 1, null, 1)
with test (col) as
(
select '1236:10:EX' from dual union all
select '1543::Ex' from dual
)
select regexp_replace(col, '(:(.*):)|.', '\2') from test;
Use regexp_substr like this to handle NULL list elements. The 4th argument is the element in the list you want:
with test (col) as
(
select '1236:10:EX' from dual union all
select '1543::Ex' from dual
)
select regexp_substr(col, '(.*?)(:|$)', 1, 2, NULL, 1) from test;

Split a string based on hyphen

I have a string like this
XX0099-X01
I would like to split the string into two based on the hyphen, i.e.
XX0099 and X01
I have tried as
SELECT 'XX0099-X01',
SUBSTR('XX0099-X01',
1,
INSTR('XX0099-X01',
'-',
1
) -1
)
FROM dual
Not sure how to get the second part.
We have an old legacy system which still using 8i Oracle database.
Using combination of substr and instr:
select
substr(s, 1, instr(s, '-') - 1),
substr(s, instr(s, '-') + 1)
from t;
Another way is using regexp_substr if supported:
select
regexp_substr('XX0099-X01','[^-]+', 1, 1),
regexp_substr('XX0099-X01','[^-]+', 1, 2)
from dual;
If you can't use a regex substring/replacement, here is an option which uses Oracle's base string functions:
SELECT SUBSTR(col, 1, INSTR(col, '-') - 1) AS first_part,
SUBSTR(col, INSTR(col, '-') + 1) AS second_part
FROM yourTable