sql - Oracle、正则表达式、以分号分隔的字符串

标签 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' 更改为 '; ;参数10' -> param10 在第 10 行,但这是我做不到的。

似乎更长的';'序列oracle 对待总是像有分号 -1 的数量。

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

最佳答案

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

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

这意味着您可以:

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         

关于sql - Oracle、正则表达式、以分号分隔的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47905492/

相关文章:

sql - 具有不同时间戳的重复条目

带有 wiki 文本的 Python 正则表达式

sql - 在 oracle 的列中添加分数约束

eclipse - 使用 Tomcat 的 Oracle 连接错误

sql - 如何在 Windows 应用商店应用程序中从 SQLite 数据库获取单行?

sql - 防止展平 View 后重新排序

javascript - 在 JS 中添加美元符号以优化网站的价格

oracle - 如何在oracle触发器中获取准确更新的列名称?

mysql - 如何设置包含完整时间戳的列等于时间戳的一部分的 SQL 查询

python - 找到字符串的精确匹配