2013-07-11 23 views
8

我正在使用Oracle 11g,並且我想使用REGEXP_SUBSTR來匹配給定模式的所有事件。 例如Oracle 11g通過正則表達式獲得所有匹配事件

SELECT 
    REGEXP_SUBSTR('Txa233141b Ta233141 Ta233142 Ta233147 Ta233148', 
    '(^|\s)[A-Za-z]{2}[0-9]{5,}(\s|$)') "REGEXP_SUBSTR" 
    FROM DUAL; 

只返回第一個匹配Ta233141但我想返回匹配正則表達式的其他事件,這意味着Ta233142 Ta233147 Ta233148。

回答

15

REGEXP_SUBSTR只返回一個值。你可以把你的字符串變成一個僞表,然後查詢匹配。有逃逸我目前這樣做的一個基於XML的方式,但使用連接,通過作品,只要你只有一個源字符串:

SELECT REGEXP_SUBSTR(str, '[^ ]+', 1, LEVEL) AS substr 
FROM (
    SELECT 'Txa233141b Ta233141 Ta233142 Ta233147 Ta233148' AS str FROM DUAL 
) 
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(str, '[^ ]+')) + 1; 

...給你:

SUBSTR    
-------------------- 
Txa233141b   
Ta233141    
Ta233142    
Ta233147    
Ta233148    

...你可以過濾,與原有模式的稍微簡單一些的版本:

SELECT substr 
FROM (
    SELECT REGEXP_SUBSTR(str, '[^ ]+', 1, LEVEL) AS substr 
    FROM (
     SELECT 'Txa233141b Ta233141 Ta233142 Ta233147 Ta233148' AS str 
     FROM DUAL 
    ) 
    CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(str, '[^ ]+')) + 1 
) 
WHERE REGEXP_LIKE(substr, '^[A-Za-z]{2}[0-9]{5,}$'); 

SUBSTR    
-------------------- 
Ta233141    
Ta233142    
Ta233147    
Ta233148    

這是不是很漂亮,但沒有在一個領域是持有多個值。

+0

非常感謝。這對我幫助很大。 – florins

+2

此代碼不返回Ta233148。 (REGEXP_REPLACE(str,'[^] +'))以CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(str,'[^] +'))+ 1 – sakthi

+0

直接使用此代碼除了簡單的分割字符之外的任何東西都會返回許多結果。 用REGEXP_COUNT(str,'[^] +')替換LENGTH(REGEXP_REPLACE(str,'[^] +'))+ 1,您將得到預期的結果。 – bkqc

1

如何添加將循環並返回所有值的函數?

create or replace function regexp_substr_mr (
    p_data clob, 
    p_re varchar 
) 
return varchar as 
    v_cnt number; 
    v_results varchar(4000); 
begin 
    v_cnt := regexp_count(p_data, p_re, 1,'m'); 
    if v_cnt < 25 then 
    for i in 1..v_cnt loop 
     v_results := v_results || regexp_substr(p_data,p_re,1,i,'m') || chr(13) || chr(10); 
    end loop; 
    else 
    v_results := 'WARNING more than 25 matches found'; 
    end if; 

    return v_results; 
end; 

然後,只需調用該函數作爲選擇查詢的一部分。

+0

原則上我更喜歡這種方法,因爲我認爲它比普遍接受的解決方案更具普遍適用性。然而,我會通過傳遞p_data,p_re和flags來創建一個類似於「create或replace type mytype is table of varchar2(4000)」的類型並從函數返回它。然後可以將其嵌入到SQL中,如下所示:從someTable中選擇A.id,X.column_value交叉連接表(regexp_substr_mr(A.textToSearch,'regexp')X – Pancho

-1

以下是您的問題的簡單解決方案。

SELECT REGEXP_SUBSTR('Txa233141b Ta233141 Ta233142 Ta233147 Ta233148', 
    '([a-zA-Z0-9]+\s?){1,}') "REGEXP_SUBSTR" 
    FROM DUAL; 
+0

這只是返回原始字符串;它還包括Txa233141b甚至儘管它以三個非數字字符開始,而不是OP的模式所需要的兩個字符。 –

0

我修復@Alex普爾answer多線源支持和更快速地執行:

with templates as (select '\w+' regexp from dual) 
select 
    regexp_substr(str, templates.regexp, 1, level) substr 
from (
    select 1 id, 'Txa233141b Ta233141 Ta233142 Ta233147 Ta233148' as str from dual 
    union 
    select 2 id, '2 22222222222222Ta233141 2Ta233142 2Ta233147' as str from dual 
    union 
    select 3 id, '3Txa233141b 3Ta233141 3Ta233142' as str from dual 
) 
join templates on 1 = 1 
connect by 
    id = connect_by_root id 
    and regexp_instr(str, templates.regexp, 1, level) > 0 
order by id, level 

來源行:

ID STR            
-- ---------------------------------------------- 
1 Txa233141b Ta233141 Ta233142 Ta233147 Ta233148 
2 2 22222222222222Ta233141 2Ta233142 2Ta233147  
3 3Txa233141b 3Ta233141 3Ta233142     

結果:

Txa233141b    
Ta233141     
Ta233142     
Ta233147     
Ta233148     
2      
22222222222222Ta233141 
2Ta233142    
2Ta233147    
3Txa233141b    
3Ta233141    
3Ta233142    
1

Thi s有點遲,但我基本上需要同樣的東西,找不到一個好的片段。我需要搜索某個表格的免費文本列並收集它們。由於這可能對另一個有用,我已經包含了一個基於這個問題的版本。雖然REGEXP_SUBSTR只返回一個值,但Oracle還提供了一個REGEXP_COUNT來告訴您給定字符串中有多少匹配項目,因此您可以將它與一系列索引一起加入,以便按如下方式選擇每個匹配項目(對於上面的單行'source_table'):

WITH source_table 
    AS (SELECT 'Txa233141b Ta233141 Ta233142 Ta233147 Ta233148' as free_text 
      FROM dual) 
    , source 
    AS (SELECT cnt 
       , free_text 
      FROM (SELECT RegExp_Count(free_text, '(^|\s)[A-Za-z]{2}[0-9]{5,}(\s|$)') AS cnt 
         , free_text 
       FROM source_table) 
      WHERE cnt > 0) 
    , iota 
    AS (SELECT RowNum AS idx 
      FROM dual 
      CONNECT BY RowNum <= (SELECT Max(cnt) FROM source)) 
SELECT UNIQUE 
     RegExp_SubStr(s.free_text, '(^|\s)[A-Za-z]{2}[0-9]{5,}(\s|$)', 1, i.idx) AS result 
FROM source s 
    JOIN iota i 
    ON (i.idx <= s.cnt) 
相關問題