Split string using pl / sql using a null connection layer
I am using this following code in Oracle pl / sql (Version: Oracle Database 11g Release 11.2.0.1.0)
select regexp_substr('A~B~C','[^~]+',1,level) output
from dual
connect by level <= length(regexp_replace('A~B~C','[^~]+')) + 1
which gives the following results:
row1: A
row2: B
row3: C
This is perfect, but I have to give a null value, that is:
select regexp_substr('~B~C','[^~]+',1,level) output
from dual
connect by level <= length(regexp_replace('~B~C','[^~]+')) + 1
I expected and wanted the following:
row1: <null>
row2: B
row3: C
but got this output:
row1: B
row2: C
row3: null
Am I doing pl / sql code wrong? How can I get it to work correctly?
source to share
Because I used single characters as an example in my question, but as a practical matter I use long strings in my project, like "How ~ do ~ I ~ do ~ this"
I found this solution from OTN Oracle.com , thanks to chris227.
SELECT CAST(REGEXP_SUBSTR (str, '(.*?)(~|$)', 1, level, null, 1) AS CHAR(12)) output
FROM (select 'How~do~I~do~this' as str from dual)
CONNECT BY level <= regexp_count(str, '~') + 1;
This will work even with single characters.
Hope this helps others looking for similair solutions.
source to share
you can concatenate INSTR
und SUBSTR
to achieve your desired result:
select
str,
replace(substr(str,
case level
when 1 then 0
else instr( str, '~',1, level-1)
end
+1,
1
), '~')
from ( select 'A~B~C~D~E' as str from dual)
connect by level <= length(regexp_replace(str,'[^~]+')) + 1
;
source to share
You can use NULLS FIRST
in a sentenceORDER BY
select regexp_substr('~B~C','[^~]+',1,level) output
from dual
connect by level <= length(regexp_replace('~B~C','[^~]+')) + 1
ORDER BY regexp_substr('~B~C','[^~]+',1,level) NULLS FIRST;
For a quote from Oracle documentation
If zero order is not specified, then processing of zero value:
NULLS LAST if the sort is ASC
NULLS FIRST if the sort is DESC
If neither ascending nor descending order is specified, and zero order is also not specified, both defaults are used, and thus the order will be ascended with NULLS LAST.
source to share
Since this issue was fresh in my opinion and I happened to see this post, I respectfully submit my suggestion, which builds on the answer by user3767503. This reduces the number of function calls required. It uses some 11g updates for regexp_substr()
and uses regexp_count()
, which I believe was also introduced in 11g. The number of fields is assumed to be the number of separators plus one.
select regexp_substr('AAA~X~C~~DD~~~E', '([^~]*)(~|$)', 1, level, null, 1) output, level
from dual
connect by level <= regexp_count('AAA~X~C~~DD~~~E','~') + 1
ORDER BY level;
See this post for more information and details on reading a regex pattern: Split Partial Values in Columns .
Bottom Line is a commonly used regex pattern '[^<delimiter>]+'
to parse a string if there is zero in the list and should be avoided IMHO.
source to share