2016-07-13 3 views
2

Oracle 데이터베이스의 열 길이가 다른 시스템의 필드보다 긴 문제가 있습니다.오라클에서 Regex_substr을 사용하여 n 문자 길이 이내의 마지막 공백까지 문자열 선택

따라서 길이가 40자가 넘는 문자열을 분할하기 위해 substr과 함께 case 문을 사용하려고합니다. 지금까지의 case 문은 column_a에 문자열의 처음 40자를 남긴 다음 나머지 문자열을 column_b에 넣는다는 사실에서 내가 원하는 것을 수행합니다.

그러나 문제는 단지 substr을 사용함으로써 문자열이 단어의 중간 부분으로 분리된다는 것입니다.

  1. 40 자 이내로 마지막 공간에 문자열 UP을 선택 - - column_a
  2. 을 위해 사람이됩니다 내가 regex_substr와 함께 사용할 수있는 정규 표현식의 몇 가지를 알고있는 경우

    그래서 궁금 해서요 40 자 이내로 마지막 공간 AFTER 문자열을 선택 - column_b에 대한

이 내가 SUBSTR으로 지금까지 가지고있는 경우 문은 다음과 같습니다

CASE WHEN Length(column_a) > 10 THEN SubStr(column_a, 0, 40) END AS column_a, 

CASE WHEN Length(column_a) > 40 THEN SubStr(addressnum, 41) END AS column_b 

정규식에 익숙하지 않아 도움이 될 것입니다.

+0

가가에 그 분할을 보장입니다. 포지션 40 이전의 마지막 공간은 모든 경우에 사용할 수 있습니까? 이 질문에는 두 부분이 있습니다. 첫째, 모든 입력 문자열은 80 자 미만입니까? 두 번째, 위치 40 이전의 마지막 공간이 위치 35에 있고 나머지 문자열이 42자인 경우 어떻게해야합니까? 그리고 - 그 공간으로 무엇을하고 싶니? - 첫 번째 줄에 그것을 포함 시키시겠습니까? 두 번째 문자열? 또는 두 문자열 중 하나에 포함시키지 않습니까? – mathguy

답변

2

나는 INSTR/SUBSTR으로 해결했습니다

select substr(column_a,1,instr(substr(column_a,1,40), ' ', -1)) column1, 
     substr(column_a,instr(substr(column_a,1,40), ' ', -1)+1, 40) column2 
from table1 
+0

훌륭하지만 아무리 잘 생각해도 완벽하게 작동합니다! 도와 주셔서 대단히 감사합니다. –

+0

@NickMoth great! catch는 Instr이 -1 인 세 번째 매개 변수가 거꾸로 간다는 것입니다. – vercelli

0

매우 비슷한 문제는 OTN 오늘 게시했습니다. https://community.oracle.com/message/13928697#13928697

여기 제안 된 문제를 다루는 일반적인 해결책을 게시했습니다. 나중에 비슷한 요구가있는 경우 유용 할 수 있습니다.

여기에 게시 된 문제의 경우 row_lengths 테이블에는 r_id = 1r_len = 40 인 행이 하나만 있습니다. 데모 목적으로 나는 OTN에서 사용한 것과 다른 input_strings 아래에 게재하고 있습니다.

설정 :

create table input_strings (str_id number, txt varchar2(500)); 

insert into input_strings values (1, 
    'One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents'); 
insert into input_strings values (2, null); 
insert into input_strings values (3, 'Mathguy rules'); 

create table row_lengths (r_id number, r_len number); 

insert into row_lengths values (1, 40); 

commit; 

select * from input_strings; 

STR_ID TXT 
------- --------------------------------------------------------------------------------- 
     1 One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents 
     2 
     3 Mathguy rules 

3 rows selected 

select * from row_lengths; 

    R_ID  R_LEN 
------- ---------- 
     1   40 

1 row selected. 

쿼리 및 출력은 : (참고 : 나는 첫 번째 토큰은 더 이상 40 자 이하인지 확인 토큰 길이를 포함 영업 이익은 대답하지 않았다 두 번째 토큰이 할 수 있습니다. 40 자, 그것은, 하나는 모든 행에 대해 r_len = 40와 아마의 row_lengths 테이블에 행을 추가 할 수없는 경우)

with 
    r (r_id, r_len) as (
     select r_id   , r_len from row_lengths union all 
     select max(r_id) + 1, 4000 from row_lengths union all 
     select max(r_id) + 2, null from row_lengths 
    ), 
    b (str_id, str, r_id, token, prev_pos, new_pos) as (
     select str_id, txt || ' ', -1, null, null, 0 
     from input_strings 
     union all 
     select b.str_id, b.str, b.r_id + 1, 
       substr(str, prev_pos + 1, new_pos - prev_pos - 1), 
       b.new_pos, 
       new_pos + instr(substr(b.str, b.new_pos + 1, r.r_len + 1) , ' ', -1) 
     from b join r 
       on b.r_id + 2 = r.r_id   
    ) 
select str_id, r_id, token, nvl(length(token), 0) as len 
from  b 
where r_id > 0 
order by str_id, r_id; 

STR_ID R_ID TOKEN            LEN 
------- ------- ------------------------------------------------ ------- 
     1  1 One Hundred Sixty-Nine Thousand Eight     37 
     1  2 Hundred Seventy-Four Dollars And Nine Cents   43 
     2  1              0 
     2  2              0 
     3  1 Mathguy rules           13 
     3  2              0 

6 rows selected. 
관련 문제