Sql 正则表达式从列表中选择第n个值,允许为空

Sql 正则表达式从列表中选择第n个值,允许为空,sql,regex,oracle,plsql,oracle11g,Sql,Regex,Oracle,Plsql,Oracle11g,我使用REGEXP\u SUBSTR()从逗号分隔的列表返回第n个值。当所有值都存在时,这可以正常工作,但如果项为null,则会失败。下面是一个示例,其中所有值都存在,并且我选择了第二次出现的1个或多个非逗号字符: SQL> select REGEXP_SUBSTR('1,2,3,4,5,6', '[^,]+', 1, 2) data 2 from dual; D - 2 但是当第二个值为null时,我实际上得到了列表中的第三项,这当然是第二次出现1个或多个非逗号字符。但是,我需

我使用
REGEXP\u SUBSTR()
从逗号分隔的列表返回第n个值。当所有值都存在时,这可以正常工作,但如果项为null,则会失败。下面是一个示例,其中所有值都存在,并且我选择了第二次出现的1个或多个非逗号字符:

SQL> select REGEXP_SUBSTR('1,2,3,4,5,6', '[^,]+', 1, 2) data
  2  from dual;

D
-
2
但是当第二个值为null时,我实际上得到了列表中的第三项,这当然是第二次出现1个或多个非逗号字符。但是,我需要它返回NULL,因为第二项为空:

SQL> select REGEXP_SUBSTR('1,,3,4,5,6', '[^,]+', 1, 2) data
  2  from dual;

D
-
3
如果我将正则表达式更改为允许零个或多个字符,而不是1个或多个字符,则对于超过null的数字也会失败:

SQL> select REGEXP_SUBSTR('1,,3,4,5,6', '[^,]*', 1, 4) data
  2  from dual;

D
-
3

我需要允许空值,但似乎无法获得正确的语法。从逻辑上讲,无论数据是否存在,我都需要返回第n次出现逗号之前的值(并考虑最后一个值)。有什么想法吗?

像这样残忍的事情怎么样:

select REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2) data
from dual
返回字符串值。您可以使用case获得实
NULL

select (case when REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2) = 'NULL'
             then NULL
             else REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2)
        end)
from dual;

可能有一个只有regexp的解决方案,但这是首先想到的。

感谢那些回复者。在仔细阅读您的答案和提供的链接中的答案后,我得出了以下解决方案:

SQL> select REGEXP_SUBSTR('1,,3,4,5', '(.*?)(,|$)', 1, 2, NULL, 1) data
  2  from dual;

Data
----
这可以描述为“查看第二次出现的可选零个或多个字符集,后跟逗号或行尾,并返回第一个子组(即数据减去逗号或行尾)

我忘了提到我在不同的位置测试了null,多个null,选择不同的位置,等等

我能找到的唯一警告是,如果您查找的字段大于可用的数字,它只返回NULL,因此您需要注意这一点。对于我的情况,这不是问题

编辑:我正在更新已被接受的答案,以方便将来可能偶然发现这一点的搜索者

下一步是封装代码,以便将其制作成更简单、可重用的函数。以下是函数源:

  FUNCTION  GET_LIST_ELEMENT(string_in VARCHAR2, element_in NUMBER, delimiter_in VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
    BEGIN
      RETURN REGEXP_SUBSTR(string_in, '(.*?)(\'||delimiter_in||'|$)', 1, element_in, NULL, 1);
  END GET_LIST_ELEMENT;
这对可能不太熟悉正则表达式的开发人员隐藏了正则表达式的复杂性,并使代码在使用时更干净。这样调用它可以获得第四个元素:

select get_list_element('123,222,,432,555', 4) from dual;

这是重复的。解析带有null的csv字符串是一个常见问题(例如)。我偏爱我的解决方案(在字符串前面加逗号,并使您的正则表达式模式为“,[^,]*’。接下来,LTRIM匹配的regexp_substr。我非常喜欢使用交替运算符、字符组以及传递子表达式的能力(例如,1作为第一个子表达式)。我在11g中没有意识到这一新增功能。@Aramillo-谢谢!今天的学习体验很有趣。Patrick-我也没有意识到,直到我阅读了你指给我的那篇文章,并在指定11g时重新搜索了REGEXP_SUBSTR的手册页。所以,谢谢!确实:)可能工作正常,直到您尝试将包含NULL的数据作为文本加载,并且希望保持这种方式。不过这不是一个坏主意。。。