REGEX从列表中select第n个值,允许空值

我正在使用REGEXP_SUBSTR()从逗号分隔的列表中返回第n个值。 当所有值都存在时,这工作正常,但如果一个项目为空,则失败。 下面是一个在所有值都存在的情况下工作的例子,我select第二个出现的不是逗号的一个或多个字符:

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

但是当第二个值为空时,我真的得到了列表中的第三个项目,当然这确实是第二个出现的一个或多个不是逗号的字符。 但是,我需要它作为第二个项目是空的返回NULL:

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

如果我更改正则expression式以允许零个或多个字符而不是一个或多个字符,则对于超过null的数字也会失败:

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

我需要允许null,但似乎无法得到正确的语法。 从逻辑上讲,我需要返回第n个逗号之前是否存在数据(也允许最后一个值)。 有任何想法吗?

感谢那些回答。 仔细阅读所提供链接的答案和答案后,我到达了这个解决scheme:

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

这可以被描述为“查看第二次出现的零个或多个字符的可选集合,后面接着一个逗号或者行尾,并且返回第一个子组(数据不是逗号或者结尾)线)。

我忘了提及我在各种职位,多个空值,select各种职位等方面进行了testing。

我能find的唯一的警告是,如果你所寻找的领域大于可用的数量,它只是返回NULL,所以你需要知道这一点。 对我的情况不是问题。

编辑:我正在更新接受的答案为未来的search者可能会偶然发现这一点的好处。

下一步是封装代码,使其可以变成一个更简单,可重用的函数。 这里是function来源:

  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; 

这隐藏了开发人员可能不太习惯的正则expression式的复杂性,并在使用时使代码更清洁。 像这样调用它来获得第四个元素:

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

如此残酷的事情如何:

 select REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2) data from dual 

这将返回string值。 你可以使用一个实例来获得一个真正的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_解决scheme,但这是首先想到的。