2014-08-27 138 views
1

我有一個regex_substr不遵守空值的問題。Oracle REGEX_SUBSTR不遵守空值

select 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 1) AS phn_nbr, 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 2) AS phn_pos, 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 3) AS phn_typ, 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 4) AS phn_strt_dt, 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 5) AS phn_end_dt, 
REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 6) AS pub_indctr 
from dual; 

如果phn_end_dt爲null並且pub_indctr不爲空,pub_indctr的值被轉移到phn_end_dt。

結果: -

PHN_NBR PHN_POS PHN_TYP PHN_STRT_DT PHN_END_DT PUB_INDCTR 
---------- ------- ------- ----------- ---------- ------------ 
2035197553 2  S  14-JUN-14 P 

雖然它應該是

PHN_NBR PHN_POS PHN_TYP PHN_STRT_DT PHN_END_DT PUB_INDCTR 
---------- ------- ------- ----------- ---------- ------------ 
2035197553 2  S  14-JUN-14    P 

有什麼建議?

回答

0

感謝您指出我在正確的方向,我甲肝e用這個來解決這個問題。

SELECT REGEXP_SUBSTR (val, '([^,]*),|$', 1, 1, NULL, 1) phn_nbr , REGEXP_SUBSTR (val, '([^,]*),|$', 1, 2, NULL, 1) phn_pos , REGEXP_SUBSTR (val, '([^,]*),|$', 1, 3, NULL, 1) phn_typ , REGEXP_SUBSTR (val, '([^,]*),|$', 1, 4, NULL, 1) phn_strt_dt , REGEXP_SUBSTR (val, '([^,]*),|$', 1, 5, NULL, 1) phn_end_dt , REGEXP_SUBSTR (val || ',', '([^,]*),|$', 1, 6, NULL, 1) pub_indctr FROM (SELECT '2035197553,2,S,14-JUN-14,,P' val FROM dual );

Oracle版本: - Oracle數據庫11g企業版發佈11.2.0.4.0 - 64位生產

1

你需要改變這一行,

REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]+', 1, 5) AS phn_end_dt, 

到,

REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]*', 1, 5) AS phn_end_dt, 
               ^

[^,]+意味着它不,一次或多次匹配任何字符。 [^,]*表示它匹配任何不爲,的字符零次或多次。因此[^,]+假設必須有一個不會出現的單個字符,。但真的沒有,通過將+更改爲*使正則表達式引擎匹配一個空字符。

+0

感謝您指出我在正確的方向,我都用這個來解決這一問題。 SELECT REGEXP_SUBSTR(val,'([^,] *),| $',1,1,NULL,1)phn_nbr ,REGEXP_SUBSTR(val,'([^,] *),| $',1,2 ,NULL,1)phn_pos ,REGEXP_SUBSTR(val,'([^,] *),| $',1,3,NULL,1)phn_typ ,REGEXP_SUBSTR(val,'([^,] *),| | $',1,4,NULL,1)phn_strt_dt ,REGEXP_SUBSTR(val,'([^,] *),| $',1,5,NULL,1)phn_end_dt ,REGEXP_SUBSTR(val ||' ,'([^,] *),| $',1,6,NULL,1)pub_indctr FROM(SELECT'2035197553,2,S,14-JUN-14,P'val FROM dual); – Ankit 2014-08-27 14:25:34

+0

@Ankit:你可以取消將此標記爲答案,並將解決方案作爲答案發布。由於Avinash Raj的回答是錯誤的。 – Wouter 2015-08-14 11:50:57

+0

@Avinash Raj:您測試了哪個Oracle版本?對於字符串中的每個逗號,我得到一個NULL值,所以P值最終在第10個捕獲組中。我在第5個捕獲組中獲得了S值。使用Oracle 12c – Wouter 2015-08-14 11:53:47

2

你能解決你的任務是這樣的:

with t(val) as (
    select '2035197553,2,S,14-JUN-14,,P' from dual 
), t1 (val) as (
    select ',' || val || ',' from t 
) 
select substr(val, REGEXP_INSTR(val, ',', 1, 1) + 1, REGEXP_INSTR(val, ',', 1, 1 + 1) - REGEXP_INSTR(val, ',', 1, 1) - 1) a 
    , substr(val, REGEXP_INSTR(val, ',', 1, 2) + 1, REGEXP_INSTR(val, ',', 1, 2 + 1) - REGEXP_INSTR(val, ',', 1, 2) - 1) b 
    , substr(val, REGEXP_INSTR(val, ',', 1, 3) + 1, REGEXP_INSTR(val, ',', 1, 3 + 1) - REGEXP_INSTR(val, ',', 1, 3) - 1) c 
    , substr(val, REGEXP_INSTR(val, ',', 1, 4) + 1, REGEXP_INSTR(val, ',', 1, 4 + 1) - REGEXP_INSTR(val, ',', 1, 4) - 1) d 
    , substr(val, REGEXP_INSTR(val, ',', 1, 5) + 1, REGEXP_INSTR(val, ',', 1, 5 + 1) - REGEXP_INSTR(val, ',', 1, 5) - 1) e 
    , substr(val, REGEXP_INSTR(val, ',', 1, 6) + 1, REGEXP_INSTR(val, ',', 1, 6 + 1) - REGEXP_INSTR(val, ',', 1, 6) - 1) f 
    from t1 

    A  B C  D  E F 
------------------------------------- 
2035197553 2 S 14-JUN-14 - P 
+0

無論您是否使用正則表達式,您的解決方案都能很好地工作。當然,如果沒有正則表達式,性能會更好。 – 2014-08-27 16:12:45

+0

謝謝,沒有REGEXP,我沒有測試它 – zaratustra 2014-08-27 19:28:11

2

典型的CSV解析方法如下:

WITH t(csv_str) AS 
    (SELECT '2035197553,2,S,14-JUN-14,,P' FROM dual 
    UNION ALL 
    SELECT '2035197553,2,S,14-JUN-14,,' FROM dual 
) 
SELECT LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 1), ',') AS phn_nbr, 
    LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 2), ',') AS phn_pos, 
    LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 3), ',') AS phn_typ, 
    LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 4), ',') AS phn_strt_dt, 
    LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 5), ',') AS phn_end_dt, 
    LTRIM(REGEXP_SUBSTR (',' 
    || csv_str, ',[^,]*', 1, 6), ',') AS pub_indctr 
FROM t 

我想打一個逗號前述我的CSV,然後我會算逗號與非逗號模式。

其具有以下搜索模式

的搜索模式查找第n個串(第n個對應與在CSV的第n個元素)的說明:

-The圖案以' ,'

- 接下來是模式'[^,]'。這只是一個不匹配的列表表達式。插入符號^表示不應匹配列表中的下列字符。

- 這個不匹配的字符列表有量詞,*,這意味着這可能發生0次或更多次。

~~~~~~~~~~~~~~~~~~~~~~~~~~~

一旦找到匹配,我也將使用LTRIM函數刪除我使用reg表達式後的逗號。

這種方法的好處在於搜索模式的發生將始終與逗號的出現相對應。

2

我怕你接受的答案不處理,你所需要的零位後的值的情況下(試圖獲得第6場):

SQL> select REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '[^,]*', 1, 6) phn_end 
_dt 
    2 from dual; 

P 
- 

你需要這樣做,而不是相信(工程11g上):

SQL> select REGEXP_SUBSTR ('2035197553,2,S,14-JUN-14,,P', '([^,]*)(,|$)', 1, 6, 
NULL, 1) phn_end_dt 
    2 from dual; 

P 
- 
P 

張貼我自己的問題後,我才發現這一點:REGEX to select nth value from a list, allowing for nulls