programing

Oracle 11g은 정규식으로 일치하는 모든 항목을 가져옵니다.

skycolor 2023. 7. 21. 21:29
반응형

Oracle 11g은 정규식으로 일치하는 모든 항목을 가져옵니다.

저는 Oracle 11g을 사용하고 있으며 REGEXP_SUBSTR을 사용하여 주어진 패턴에 대한 모든 발생 항목을 일치시키고 싶습니다.예를들면

 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을 반환합니다.

REGEXP_SUBSR은 하나의 값만 반환합니다.문자열을 유사 테이블로 변환한 다음 일치 항목을 쿼리할 수 있습니다.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             

그다지 예쁘지는 않지만, 한 분야에 여러 가지 가치가 있는 것은 아닙니다.

조금 늦었지만 기본적으로 같은 것이 필요했고 좋은 스니펫을 찾을 수 없었습니다.표의 자유 텍스트 열에서 몇 가지 용어를 검색하여 수집해야 했습니다.이것이 다른 사람에게 유용할 수도 있기 때문에 이 질문에 기반한 버전을 포함했습니다.REGEXP_SUBSR은 하나의 값만 반환하지만 Oracle은 지정된 문자열에 얼마나 많은 일치 항목이 있는지 알려주는 REGEXP_COUNT도 제공하므로 이 값에 다음과 같이 인덱스 목록을 결합하여 각 항목을 선택할 수 있습니다(이 쿼리의 예제를 일부 'source_table'의 자유 텍스트로 사용).

DEFINE MATCH_EXP = "'(^|\s)[A-Za-z]{2}[0-9]{5,}'"

WITH source_table
     -- Represents some DB table with a 'free_text' column to be checked.
     AS (       ( SELECT 'Txa233141 Ta233141 Ta232 Ta233142 Ta233141 Ta233148'
                             AS free_text FROM dual )
          UNION ( SELECT 'Other stuff PH33399 mixed in OS4456908843 this line'
                             AS free_text FROM dual )
        )
   , source
     -- For some table, select rows of free text and add the number of matches
     -- in the line.
     AS ( SELECT cnt
               , free_text
          FROM ( SELECT RegExp_Count(free_text, &MATCH_EXP) AS cnt
                      , free_text 
                 FROM source_table )
          WHERE cnt > 0 )
   , iota
     -- Index generator
     AS ( SELECT RowNum AS idx
          FROM dual
          CONNECT BY RowNum <= ( SELECT Max(cnt) FROM source ) )
-- Extract the unique 'cnt' matches from each line of 'free_text'.
SELECT UNIQUE
       RegExp_SubStr(s.free_text, &MATCH_EXP, 1, i.idx) AS result
FROM   source s
  JOIN iota i
    ON ( i.idx <= s.cnt )
ORDER BY result ASC
;

선택한 행 목록에서 작업할 수 있는 장점이 있으며, 매우 느릴 수 있으므로 연결 기준을 최소로 사용합니다.

루프를 통해 모든 값을 반환하는 기능을 추가하는 것은 어떻습니까?

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;

그런 다음 선택 쿼리의 일부로 함수를 호출합니다.

다중 회선 소스 지원 및 보다 신속한 실행을 위해 @Alex Pool 답변 수정합니다.

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               

@David E를 기준으로 합니다.벨리예프 답변입니다. 다중 행 입력에 대한 쿼리입니다.아래의 질문이 당신에게 도움이 된다면, 원래의 답변을 투표로 올리는 것을 고려해보세요.

SELECT SUBSTR
  FROM (WITH TEMPLATES AS (SELECT '\w+' REGEXP FROM DUAL)
         SELECT ID,
                CONNECT_BY_ROOT ID CBR,
                LEVEL LVL,
                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 REGEXP_INSTR(STR, TEMPLATES.REGEXP, 1, LEVEL) > 0)
          WHERE ID = CBR
          GROUP BY ID,
                   CBR,
                   LVL,
                   SUBSTR
          ORDER BY ID,
                   LVL;

입력:

ID STR==  ==============================================1 Txa233141b Ta233141Ta233142Ta233147Ta23314822 222222222222Ta233141 2Ta233142 2Ta23314733Txa233141b 3Ta233141 3Ta233142

출력:

서브스트======================Txa233141bTa233141Ta233142Ta233147Ta2331482222222222222Ta2331412Ta2331422Ta2331473Txa233141b3Ta2331413Ta233142
SELECT  
  LISTAGG(REGEXP_SUBSTR('Txa233141b Ta233141 Ta233142 Ta233147 Ta233148', '(^|\s)[A-Z]{2}[0-9]{5,}',1,level) 
         ) WITHIN GROUP(ORDER BY 1)
  AS REGEXP_SUBSTR
FROM DUAL
CONNECT BY level<=regexp_count('Txa233141b Ta233141 Ta233142 Ta233147 Ta233148','(^|\s)[A-Z]{2}[0-9]{5,}')
;

아래는 당신의 질문에 대한 쉬운 해결책입니다.

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

언급URL : https://stackoverflow.com/questions/17596363/oracle-11g-get-all-matched-occurrences-by-a-regular-expression

반응형