Need to extract data from string by regexp_substr - oracle

I have a ["1101124","1101123","123456"], I need to get the end result as rows for the numbers which are in the bracket.
How can I achieve this by using regular expression in Oracle.

Don't use regular expression to try to parse JSON data; use a proper JSON parser:
SELECT value
FROM JSON_TABLE(
'["1101124","1101123","123456"]',
'$[*]'
COLUMNS(
value VARCHAR2(20) PATH '$'
)
)
Outputs:
VALUE
1101124
1101123
123456
db<>fiddle here

If ["1101124","1101123","123456"] is a string:
SQL> WITH DATA AS
2 ( SELECT '["1101124","1101123","123456"]' str FROM dual
3 )
4 SELECT trim(regexp_substr(str, '[0-9]+', 1, LEVEL)) str
5 FROM DATA
6 CONNECT BY regexp_substr(str , '[0-9]+', 1, LEVEL) IS NOT NULL
7 /
STR
----------------------------------------
1101124
1101123
123456
3 rows selected.
SQL>

Related

Need to remove only character which are at the end

Need to remove only characters at the end.
2014JP34343DD
2013GH43422
Output:
2014JP34343
2013GH43422
Tried regexp fuctions and even simple substr and instr function but not able to remove it.
regexp_replace seems to be a simple option:
SQL> with test (col) as
2 (select '2014JP34343DD' from dual union all
3 select '2013GH43422' from dual
4 )
5 select col,
6 regexp_replace(col, '[[:alpha:]]+$') result
7 from test;
COL RESULT
------------- -------------
2014JP34343DD 2014JP34343
2013GH43422 2013GH43422
SQL>

Extract Data Between Brackets in Oracle SQL

I have a table with data in below format
COURSE
[]
["12345"]
["12345","7890"
I want to extract the data between [] but without "
So, my output would be in below format
COURSE
12345
12345, 7890
I tried the below code which works fine for first 3 rows
select REGEXP_SUBSTR (COURSE,
'"([^"]+)"',
1,
1,
NULL,
1) from TEST;
But 4th row only results in 12345.
Why not simple translate?
SQL> with test (course) as
2 (select '[]' from dual union
3 select null from dual union
4 select '["12345"]' from dual union
5 select '["12345","7890"]' from dual
6 )
7 select course,
8 translate(course, 'a[]"', 'a') result
9 from test;
COURSE RESULT
---------------- -----------------------------------------
["12345","7890"] 12345,7890
["12345"] 12345
[]
SQL>

How to get character or string after nth occurrence of pipeline '|' symbol in ORACLE using REGULAR_EXPRESSION?

What is the regular expression query to get character or string after nth occurrence of pipeline | symbol in ORACLE? For example I have two strings as follows,
Jack|Sparrow|17-09-16|DY7009|Address at some where|details
|Jack|Sparrow|17-09-16||Address at some where|details
I want 'DY7009' which is after 3rd pipeline symbol starting from 1st position, So what will be regular expression query for this? And in second string suppose that 1st position having | symbol, then I want 4th string if there is no value then it should give NULL or BLANK value.
select regexp_substr('Jack|Sparrow|17-09-16|DY7009|Address at some where|details'
,' ?? --REX Exp-- ?? ') as col
from dual;
Result - DY7009
select regexp_substr('Jack|Sparrow|17-09-16|DY7009|Address at some where|details'
,' ?? --REX Exp-- ?? ') as col
from dual;
Result - '' or (i.e. NULL)
So what should be the regexp? Please help. Thank you in Advance
NEW UPDATE Edit ---
Thank you all guys!!, I appreciate your answer!!. I think, I didn't ask question right. I just want a regular expression to get 'string/character string' after nth occurrence of pipeline symbol. I don't want to replace any string so only regexp_substr will do the job.
----> If 'Jack|Sparrow|SQY778|17JULY17||00J1' is a string
I want to find string value after 2nd pipe line symbol here the answer will be SQY778. If i want to find string after 3rd pipeline symbol then answer will be 17JULY17. And if I want to find value after 4th pipeline symbol then it should give BLANK or NULL value because there is nothing after 4th pipeline symbol. If I want to find string 5th symbol then I will only replace one digit in Regular expression i.e. 5 and I will get 00J1 as a result.
Here ya go. Replace the 4th argument to regexp_substr() with the number of the field you want.
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select regexp_substr(str, '(.*?)(\||$)', 1, 4, NULL, 1) field_4
from tbl;
FIELD_4
--------
DY7009
SQL>
To list all the fields:
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select regexp_substr(str, '(.*?)(\||$)', 1, level, NULL, 1) split
from tbl
connect by level <= regexp_count(str, '\|')+1;
SPLIT
-------------------------
Jack
Sparrow
17-09-16
DY7009
Address at some where
details
6 rows selected.
SQL>
So if you want select fields you could use:
with tbl(str) as (
select 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details ' from dual
)
select
regexp_substr(str, '(.*?)(\||$)', 1, 1, NULL, 1) first,
regexp_substr(str, '(.*?)(\||$)', 1, 2, NULL, 1) second,
regexp_substr(str, '(.*?)(\||$)', 1, 3, NULL, 1) third,
regexp_substr(str, '(.*?)(\||$)', 1, 4, NULL, 1) fourth
from tbl;
Note this regex handles NULL elements and will still return the correct value. Some of the other answers use the form '[^|]+' for parsing the string but this fails when there is a NULL element and should be avoided. See here for proof: https://stackoverflow.com/a/31464699/2543416
Don't have enough reputation to comment on Chris Johnson's answer so adding my own. Chris has the correct approach of using back-references but forgot to escape the Pipe character.
The regex will look like this.
WITH dat
AS (SELECT 'Jack|Sparrow|17-09-16|DY7009|Address at some where|details' AS str,
3 AS pos
FROM DUAL
UNION
SELECT ' |Jack|Sparrow|17-09-16||Address at some where|details' AS str,
4 AS pos
FROM DUAL)
SELECT str,
pos,
REGEXP_REPLACE (str, '^([^\|]*\|){' || pos || '}([^\|]*)\|.*$', '\2')
AS regex_result
FROM dat;
I'm creating the regex dynamically by adding the position of the Pipe character dynamically.
The result looks like this.
|Jack|Sparrow|17-09-16||Address at some where|details (4):
Jack|Sparrow|17-09-16|DY7009|Address at some where|details (3): DY7009
You can use regex_replace to get the nth matching group. In your example, the fourth match could be retrieved like this:
select regexp_replace(
'Jack|Sparrow|17-09-16|DY7009|Address at some where|details',
'^([^\|]*\|){3}([^\|]*)\|.*$',
'\4'
) as col
from dual;
Edit: Thanks Arijit Kanrar for pointing out the missing escape characters.
To OP: regex_replace doesn't replace anything in the database, only in the returned string.
You can use this query to get the value at the specific column ( nth occurrence ) as follows
SELECT nth_string
FROM
(SELECT TRIM (REGEXP_SUBSTR (long_string, '[^|]+', 1, ROWNUM) ) nth_string ,
level AS lvl
FROM
(SELECT REPLACE('Jack|Sparrow|17-09-16|DY7009|Address at some where|details','||','| |') long_string
FROM DUAL
)
CONNECT BY LEVEL <= REGEXP_COUNT ( long_string, '[^|]+')
)
WHERE lvl = 4;
Note that i am using the standard query in oracle to split a delimited string into records. To handle blank between delimiters as in your second case, i am replacing it with a space ' ' . The space gets converted to NULL after applying TRIM() function.
You can get any nth record by replacing the number in lvl = at the end of the query.
Let me know your feedback. Thanks.
EDIT:
It seems to not work with purely regexp_substr() as there is no way to convert blank between '||' to Oracle NULL .So intermediate TRIM() was required and i am adding a replace to make it easier. There will be patterns to directly match this scenario, but could not find them.
Here are all scenarios for 4th occurence .
WITH t
AS (SELECT '|Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT 'Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT '||Jack|Sparrow|SQY778|17JULY17|00J1' long_string
FROM dual)
SELECT long_string,
Trim (Regexp_substr (mod_string, '\|([^|]+)', 1, 4, NULL, 1)) nth_string
FROM (SELECT long_string,
Replace(long_string, '||', '| |') mod_string
FROM t) ;
LONG_STRING NTH_STRING
------------------------ -----------
|Jack|Sparrow|SQY778|17JULY17||00J1 17JULY17
Jack|Sparrow|SQY778|17JULY17||00J1 NULL
||Jack|Sparrow|SQY778|17JULY17|00J1 SQY778
EDIT2: Finally a pattern that gives the solution.Thanks to Gary_W
To get the nth occurence from the string , use:
WITH t
AS (SELECT '|Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT 'Jack|Sparrow|SQY778|17JULY17||00J1' long_string
FROM dual
UNION ALL
SELECT '||Jack|Sparrow|SQY778|17JULY17|00J1' long_string
FROM dual)
SELECT long_string,
Trim (regexp_substr (long_string, '(.*?)(\||$)', 1, :n + 1, NULL, 1)) nth_string
FROM t;

How to define default escape character in Oracle?

I have table
id name
__________
1 name1
2 name2
3 _name3
and I want to select all names, that starting with '_' character.
SELECT name FROM table1 WHERE name like '_%'
But this query returns all rows from table. Maybe anyone knows some solution for this problem (without using ESCAPE keyword)? Or, is there opportunity to set default escape character in Oracle?
Apparently, you cannot:
char1 [ NOT ] { LIKE | LIKEC | LIKE2 | LIKE4 }
char2 [ ESCAPE esc_char ]
[...]
If esc_char is not specified, then there is no default escape
character.
I want to select all names, that starting with '_' character.
Use SUBSTR.
SQL> WITH DATA AS(
2 SELECT 1 ID, 'name1' NAME FROM dual UNION ALL
3 SELECT 2, 'name2' FROM dual UNION ALL
4 SELECT 3 , '_name3' FROM dual
5 )
6 SELECT * FROM DATA
7 WHERE substr(NAME, 1, 1) = '_'
8 /
ID NAME
---------- ------
3 _name3
SQL>
Try this..
select * from table1 where regexp_like (name,'^_') ;

split string in oracle query

I am trying to fetch phone numbers from my Oracle database table. The phone numbers may be separated with comma or "/". Now I need to split those entries which have a "/" or comma and fetch the first part.
Follow this approach,
with t as (
select 'Test 1' name from dual
union
select 'Test 2, extra 3' from dual
union
select 'Test 3/ extra 3' from dual
union
select ',extra 4' from dual
)
select
name,
regexp_instr(name, '[/,]') pos,
case
when regexp_instr(name, '[/,]') = 0 then name
else substr(name, 1, regexp_instr(name, '[/,]')-1)
end first_part
from
t
order by first_part
;
Lookup substr and instr functions or solve the puzzle using regexp.
I added a table test with one column phone_num. And added rows similar to your description.
select *
from test;
PHONE_NUM
------------------------------
0123456789
0123456789/1234
0123456789,1234
3 rows selected.
select
case
when instr(phone_num, '/') > 0 then substr(phone_num, 0, instr(phone_num, '/')-1)
when instr(phone_num, ',') > 0 then substr(phone_num, 0, instr(phone_num, ',')-1)
else phone_num
end phone_num
from test
PHONE_NUM
------------------------------
0123456789
0123456789
0123456789
3 rows selected.
This generally works. Although it will fail if you have rows with commas and slashes.

Resources