2014-09-03 50 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