Regex values after special character with empty values - sql

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.

Related

selected splitted value in oracle

I have two columns A, B in oracle where A value has values like that xx-target-xx
xx any data but target is exists
A
--------
xx-target-xx
xx-target
i neet to return only 'target' from text
i tired this
select TRIM(substr(A, 0, instr(A, '-') - 1)) from mytable
but the result returns xx not target
Use REGEXP_SUBSTR. You want the second string of any characters except the minus sign:
select a, regexp_substr(a, '[^-]+', 1, 2) from mytable;
Using INSTR and SUBSTR instead is a tad more complicated, but possible of course:
select a, substr(a,
instr(a, '-') + 1,
instr(a || '-', '-', 1, 2) - instr(a, '-') - 1
) as value
from mytable;
Demo: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=e75b878bbd6300e9207cd698bb3029ec

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

Substring from underscore and onwards in Oracle

I have a string with under score and some characters. I need to apply substring and get values to the left excluding underscore. So I applied below formula and its working correctly for those strings which have underscore (_). But for strings without (_) it is bringing NULL. Any suggestions how this can be handled in the substring itself.
Ex: ABC_BASL ---> Works correctly; ABC ---> gives null
My formula as below -
select SUBSTR('ABC_BAS',1,INSTR('ABC_BAS','_')-1) from dual;
ABC
select SUBSTR('ABC',1,INSTR('ABC','_')-1) from dual;
(NULL)
You could use a CASE expression to first check for an underscore:
WITH yourTable AS (
SELECT 'ABC_BAS' AS col FROM dual UNION ALL
SELECT 'ABC' FROM dual
)
SELECT
CASE WHEN col LIKE '%\_%' ESCAPE '\'
THEN SUBSTR(col, 1, INSTR(col, '_') - 1)
ELSE col END AS col_out
FROM yourTable;
Use regular expression matching:
SELECT REGEXP_SUBSTR('ABC_BAS', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;
returns 'ABC', and
SELECT REGEXP_SUBSTR('ABC', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;
also returns 'ABC'.
db<>fiddle here
EDIT
The above gives correct results, but I missed the easiest possible regular expression to do the job:
SELECT REGEXP_SUBSTR('ABC_BAS', '[^_]*') FROM DUAL;
returns 'ABC', as does
SELECT REGEXP_SUBSTR('ABC', '[^_]*') FROM DUAL;
db<>fiddle here
Yet another approach is to use the DECODE in the length parameter of the substr as follows:
substr(str,
1,
decode(instr(str,'_'), 0, lenght(str), instr(str,'_') - 1)
)
You seem to want everything up to the first '_'. If so, one method usesregexp_replace():
select regexp_replace(str, '(^[^_]+)_.*$', '\1')
from (select 'ABC' as str from dual union all
select 'ABC_BAS' from dual
) s
A simpler method is:
select regexp_substr(str, '^[^_]+')
from (select 'ABC' as str from dual union all
select 'ABC_BAS' from dual
) s
Here is a db<>fiddle.
I'd use
regexp_replace(text,'_.*')
or if performance was a concern,
substr(text, 1, instr(text||'_', '_') -1)
For example,
with demo(text) as
( select column_value
from table(sys.dbms_debug_vc2coll('ABC', 'ABC_DEF', 'ABC_DEF_GHI')) )
select text
, regexp_replace(text,'_.*')
, substr(text, 1, instr(text||'_', '_') -1)
from demo;
TEXT REGEXP_REPLACE(TEXT,'_.*') SUBSTR(TEXT,1,INSTR(TEXT||'_','_')-1)
------------ --------------------------- -------------------------------------
ABC ABC ABC
ABC_DEF ABC ABC
ABC_DEF_GHI ABC ABC
Ok i think i got it. Add nvl to the substring and insert the condition as below -
select nvl(substr('ABC',1,instr('F4001Z','_')-1),'ABC') from dual;

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;

How to get specific value from specific position by substr-instr

I have some filename like 'abc-type-bank-20200112-1578796204118.csv'
i want to get the value 'bank' from above which is 3rd value if I cut the string by '-'.
If my filename is like abc-type-XYZ-20200112-1578796204118.csv, I should get 'XYZ' from 3rd position.
I was trying to get by below code, but it giving wrong value.
select substr(v_FILE_NAME,1,instr(v_FILE_NAME, '-') + 3) as name from (
select 'abc-type-bank-20200112-1578796204118.csv' as v_FILE_NAME from dual);
To use SUBSTR and INSTR to extract your desired substring you'd do something like
WITH cteData AS (SELECT 'abc-type-bank-20200112-1578796204118.csv' AS FILENAME FROM DUAL),
ctePos AS (SELECT FILENAME,
INSTR(FILENAME, '-', 1, 2) AS DASH_2_POS,
INSTR(FILENAME, '-', 1, 3) AS DASH_3_POS
FROM cteData)
SELECT SUBSTR(FILENAME, DASH_2_POS + 1, DASH_3_POS - DASH_2_POS - 1) AS SUBSTR_3
FROM ctePos
The above will extract the substring 'bank' from the sample data.
db<>fiddle here
The use of dual suggests Oracle. In that database you can use regexp_substr():
select regexp_substr(filename, '[^-]+', 1, 3)
from (select 'abc-type-XYZ-20200112-1578796204118.csv' as filename from dual) x;