简体   繁体   中英

Regexp_Substr for Semicolon in query for ORACLE DB

I have got the REGEXP_SUBSTR to split the semi-colon but the issue is that if there is no data between two semi-colon there the next data is shifted one column before.

Here is the below example.

Data in Oracle DB column

ColumnXYZ
A;;B

Now the my query is

SELECT REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 1) as COL1,
       REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 2) as COL2,
       REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 3) as COL3,
FROM TABLE T

After execution is show below data

COL1  COL2  COl3
A      B    null

but the I need the output in below format as between two semi-colon there is no value.

COL1   COL2  COL3  
A      null  B
  SELECT   ROWNUM AS num_row,
           REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', '; ;'),';;','; ;'), '[^;]+', 1, LEVEL) AS par_value
  FROM     dual
  CONNECT  BY REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', '; ;'),';;','; ;'), '[^;]+', 1, LEVEL) IS NOT NULL

Or if You need null column:

SELECT  num_row,
        CASE
          WHEN par_value = '#$N#$' THEN NULL
          ELSE par_value
        END as par_value
FROM    (
          SELECT   ROWNUM AS num_row,
                   REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', ';#$N#$;'),';;','; ;'), '[^;]+', 1, LEVEL) AS par_value
          FROM     dual
          CONNECT  BY
                   REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', ';#$N#$;'),';;','; ;'), '[^;]+', 1, LEVEL) IS NOT NULL
        )

$N#$ is example value for null

This should work:

WITH cte AS (
    SELECT 'A;B;C' AS col FROM DUAL UNION
    SELECT 'A;B;' AS col FROM DUAL UNION
    SELECT ';B;C' AS col FROM DUAL UNION
    SELECT 'A;;C' AS col FROM DUAL UNION
    SELECT 'A;;' AS col FROM DUAL UNION
    SELECT ';B;' AS col FROM DUAL UNION
    SELECT ';;C' AS col FROM DUAL UNION
    SELECT ';;' FROM DUAL
)
SELECT col
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 1, '', 1) AS col1
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 2, '', 1) AS col2
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 3, '', 1) AS col3
FROM cte

The pattern ([^;]*)(;|$) matches zero or more non-semicolons followed by semicolon or end of string. Grouping is used to convert each match into two sub matches eg A; becomes A and ; .

You can use replace with '; ;' '; ;' argument, and then trim

with t1 as
(select replace('A;;B',';;','; ;') as str from dual 
),
     t2(col1,col2,col3) as
(
 select regexp_substr(str, '[^;]+', 1, 1),
        trim(regexp_substr(str, '[^;]+', 1, 2)),
        regexp_substr(str, '[^;]+', 1, 3) 
   from t1
)   
select * from t2;

  COL1  COL2  COL3
  ----  ----  ----
  A     null  B

Edit depending on your comment :

If you want row-wise result, consider the following query :

with t1 as
 (select replace('A;;B',';;','; ;') as str from dual)
   select trim(regexp_substr(str, '[^;]+', 1, level))
       as "Result String"
     from t1
    cross join dual
  connect by level <= length(regexp_replace(str, ';',''));

Result String
-------------
A

B

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM