Oracle,Regexp,通过分号分隔的字符串

时间:2017-12-20 11:55:10

标签: sql regex oracle connect-by

我有这个查询:

SELECT ROWNUM AS num_row,
       REGEXP_SUBSTR(REPLACE('param1;param2;param3;;param5;;param7;;;param10;param11;param12;param13;param14;param15;',
                             ';;',
                             '; ;'),
                     '[^;]+',
                     1,
                     level) AS par_value
FROM   dual
CONNECT BY REGEXP_SUBSTR(REPLACE('param1;param2;param3;;param5;;param7;;;param10;param11;param12;param13;param14;param15;',
                                 ';;',
                                 '; ;'),
                         '[^;]+',
                         1,
                         level) IS NOT NULL

带输出:

1   param1
2   param2
3   param3
4    
5   param5
6    
7   param7
8    
9   param10
10  param11
11  param12
12  param13
13  param14
14  param15

正如您已经看过(或不是),在参数7和10之间应该有两个NULL参数,但是这个查询只返回一个。

如果我在'param10'之前再添加一个分号或将';; param10'改为'; ; param10' - > param10在第10行,但这是我不能做的事情。

似乎更长的';'序列oracle总是喜欢有分号-1。

有没有人知道如何修复它?

1 个答案:

答案 0 :(得分:4)

如果我是你,我会通过在connect by子句中使用regexp_count来简化事情(看起来你的参数总是以分号结尾,所以不管有多少个冒号,你想循环遍历字符串很多次。)

此外,[^<characters>]方法不处理空值,因此您需要切换到(.*?)(;|$)的模式 - 即。零个或多个字符后跟一个分号,然后只选择第一次进行(`。*?)。

这意味着你可以这样做:

WITH sample_data AS (SELECT 'param1;param2;param3;;param5;;param7;;;param10;param11;param12;param13;param14;param15;' str FROM dual)
SELECT LEVEL AS num_row,
       REGEXP_SUBSTR(REPLACE(str,
                             ';;',
                             '; ;'),
                     '[^;]+',
                     1,
                     level) AS par_value,
       REGEXP_SUBSTR(str, '(.*?)(;)', 1, LEVEL, NULL, 1) new_str
FROM   sample_data
CONNECT BY LEVEL <= regexp_count(str, ';');

   NUM_ROW PAR_VAL NEW_STR
---------- ------- -------
         1 param1  param1
         2 param2  param2
         3 param3  param3
         4         
         5 param5  param5
         6         
         7 param7  param7
         8         
         9 param10 
        10 param11 param10
        11 param12 param11
        12 param13 param12
        13 param14 param13
        14 param15 param14
        15         param15

注意,如果尾部分号实际上意味着它后面有一个空参数,那么你需要切换到(.*?)(;|$)的模式(即零个或多个字符后跟一个分号或者字符串的结尾),加上你需要在regexp_count结果中添加一个:

WITH sample_data AS (SELECT 'param1;param2;param3;;param5;;param7;;;param10;param11;param12;param13;param14;param15;' str FROM dual)
SELECT LEVEL AS num_row,
       REGEXP_SUBSTR(REPLACE(str,
                             ';;',
                             '; ;'),
                     '[^;]+',
                     1,
                     level) AS par_value,
       REGEXP_SUBSTR(str, '(.*?)(;|$)', 1, LEVEL, NULL, 1) new_str
FROM   sample_data
CONNECT BY LEVEL <= regexp_count(str, ';') + 1;

   NUM_ROW PAR_VAL NEW_STR
---------- ------- -------
         1 param1  param1
         2 param2  param2
         3 param3  param3
         4         
         5 param5  param5
         6         
         7 param7  param7
         8         
         9 param10 
        10 param11 param10
        11 param12 param11
        12 param13 param12
        13 param14 param13
        14 param15 param14
        15         param15
        16