2014-09-03 61 views
4

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

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 

如果我改变了正则表达式来允许零个或多个字符,而不是1以上,也未能对过去空号:

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

D 
- 
3 

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

+0

这是一个重复。用空值解析csv字符串是一个常见问题(例如http://stackoverflow.com/questions/25529511/oracle-regex-substr-not-honoring-null-values/25530536#25530536)。我偏向于我的解决方案(用逗号在字符串前面,让你的正则表达式模式为',[^,] *'。接下来,LTRIM匹配regexp_substr。 – 2014-09-03 16:43:14

回答

9

感谢那些回复。细读你的答案,并在所提供的链接的答案后,我来到了这个解决方案:

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

Data 
---- 

这可谓是“看一组可选的零个或多个字符之后是第2次发生逗号或行尾,并返回第一个小组(这是数据减去逗号或行尾)

我忘了提及我在各种位置,多个空值,选择各种职位等

我可以找到唯一的警告是,如果您寻找的领域大于可用的数量,它只是返回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; 

这从开发商谁可能无法与它很舒服隐藏了正则表达式的复杂性,并使得代码更清洁反正在使用的时候。这样称呼它获得第4单元:

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

伟大的解决方案! – Aramillo 2014-09-03 20:02:34

+0

我喜欢使用交替操作符和使用字符组以及传递子表达式的能力(例如1作为第一个子表达式)。我没有意识到11g中的这个新增功能。 – 2014-09-03 20:27:33

+0

@Aramillo - 谢谢!今天有趣的学习体验。帕特里克 - 直到我读完那篇文章后,我指出并重新搜索了REGEXP_SUBSTR的手册页,同时指定了11g。那谢谢啦! – 2014-09-03 20:34:04

0

如何像这样残酷:

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

返回字符串值。你可以得到一个真正的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_ -only的解决方案,但是这是第一个浮现在脑海。

+0

确实残酷:) 可能工作正常,直到你尝试加载包含NULL的数据作为文本,并且您想要保持这种方式。不是一个坏主意,但... – Wouter 2015-08-14 12:41:37

相关问题