2017-10-18 5 views
0

STRING 내의 여러 (연속) 수평 공간을 단일 수평 공간으로 대체하는 FUNCTION이 있습니다.오라클 - 문자열 - 구두점 형식 지정 기능

STR_ORIG = 'Hello World' 
STR_NEW = 'Hello World' 

기능은 다음과 같습니다.

CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
    INS VARCHAR2) 
RETURN VARCHAR2 
AS 
OUTSTR VARCHAR2(4000); 
STR VARCHAR2(4000); 
BEGIN 
STR := INS; 
WHILE (INSTR(STR,' ',1) > 0) 
LOOP 
    OUTSTR := OUTSTR || ' ' || SUBSTR(STR,1,INSTR(STR,' ',1) - 1); 
    STR := TRIM(BOTH ' ' FROM SUBSTR(STR,INSTR(STR,' ',1))); 
END LOOP; 
OUTSTR := OUTSTR || ' ' || TRIM(STR); 
RETURN TRIM(OUTSTR); 
END CP_RDN_PUNCT; 

그러나, 나는이 FUNCTION을 확장하고 싶습니다 그래서 기본적인 문장 형식 (쉼표, 마침표 및 괄호)를 보정 할 수 있습니다. 그러나 FUNCTION이 여러 개의 (연속적인) 수평 공간을 계속 제거하는 것이 중요합니다.

예 : 출력이 출력 될 것 STR_ORIG = 'Hello.Marc' 경우 'Hello, Marc'

'Hello. Marc'

STR_ORIG = 'Hello(Marc)' 경우 출력이 'Hello (Marc)'

이 될 것입니다 될 것 STR_ORIG = 'Hello , Marc' 경우

내가 사용하고자하는 규칙은 매우 기본적인 :

Comma;...............One HORIZONTAL SPACE after a Comma. 
        No HORIZONTAL SPACE before a Comma. 

Full Stop;...........One HORIZONTAL SPACE after a Full Stop. 
        No HORIZONTAL SPACE before a Full Stop. 

Open Parenthesis;....No HORIZONTAL SPACE after an Open Parenthesis. 
        One HORIZONTAL SPACE before an Open Parenthesis. 

Closed Parenthesis;..One HORIZONTAL SPACE after an Closed Parenthesis*.   
        No HORIZONTAL SPACE before an Closed Parenthesis. 

* 참고 : 닫힌 괄호 바로 뒤에 쉼표 또는 전체 정지가 있으면 'HORIZONTAL SPACE'규칙 대신 'No HORIZONTAL SPACE'규칙이 사용됩니다.

FUNCTION이이 문제에 대한 최선의 방법이라고 생각합니다. (순수한 SQL (REG_EXP)을 사용하여 탐색했지만 코드가 매우 복잡해지기 시작합니다. 주로 데이터의 불일치로 인해). 또한 미래에 추가 규칙 (예 : 밑줄 규칙)을 추가하려는 경우 FUNCTION을 유지 관리하기가 더 쉽다고 가정합니다. 그러나 언제나처럼 나는 전문가로부터 제안을 받는다.

미리 감사드립니다.

답변

1

또 하나의 방법은 패턴 대신 일반 SQL의 교체를 저장하는 associated array을 사용하는 것입니다. 그런 다음 루프에서 문자열에 대한 각 변환을 적용합니다.

CREATE OR REPLACE FUNCTION cp_rdn_punct2 (
    inp_pattern VARCHAR2 
) RETURN VARCHAR2 AS 

    v_outstr VARCHAR2(1000) := inp_pattern; 
    TYPE v_astype IS 
     TABLE OF VARCHAR2(40) INDEX BY VARCHAR(40); 
    v_pat  v_astype; 
    v_idx  VARCHAR2(40); 

BEGIN 
    v_pat(' *, *') := ', '; 
    v_pat(' *\. *') := '. '; 
    v_pat(' *\(*') := ' ('; 
    v_pat(' *\) *') := ') '; 
    v_idx := v_pat.first; 
    WHILE v_idx IS NOT NULL LOOP 
     v_outstr := regexp_replace(v_outstr,v_idx,v_pat(v_idx)); 
     v_idx := v_pat.next(v_idx); 
    END LOOP; 

    RETURN v_outstr; 
END; 
/
+0

이것은 훌륭한, @ Kaushik Nayak! 이 일을 할 시간을 내 주셔서 감사합니다. 많은 감사드립니다. – MAndrews

1

INSTR, SUBSTR을 사용하는 것보다 REGEXP을 사용하여 함수를 작성할 수 있습니다.

참고 :이 기능은 동일한 문자열에 나타나는 여러 유형의 패턴을 고려하지 않습니다. 따라서 ","및 "."이 모두 나타나면 작동하지 않습니다. 따라서 이러한 시나리오를 다루기 위해 필요한 모든 변환 코드, EXCEPTION 처리 등을 작성할 수 있습니다. 어떻게 할 수 있는지에 대한 아이디어를 당신에게주었습니다. PL/SQL과 유사한 코드의 경우 with 절 내부에 코딩되어 있으므로 IF THEN 또는 CASE 블록으로 다시 작성해야 할 수 있습니다. 내가 생각할 수

CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
    inp_pattern VARCHAR2) 
RETURN VARCHAR2 
AS 
outstr VARCHAR2(4000); 
BEGIN 
with reg (pattern, regex ,replacement) AS 

(
    select ',' , ' *, *', ', ' FROM DUAL UNION ALL 
    select '.' , ' *\. *', '. ' FROM DUAL UNION ALL 
    select '(' , ' *\(*', ' (' FROM DUAL 
) 
SELECT 
    TRIM(regexp_replace(rep,' *\) *',') ')) INTO outstr 
FROM 
    (
     SELECT 
      regexp_replace(inp_pattern,regex,replacement) rep 
     FROM 
      reg 
     WHERE 
      inp_pattern LIKE '%' 
      || pattern 
      || '%' 
    ); 

RETURN outstr; 

END; 
/
+0

감사합니다. Kaushik Nayak - 곧 테스트하겠습니다. 매우 감사. – MAndrews

+0

불행하게도, 이것은 OK로 컴파일되지만, 테스트 결과,'ORA-01422 : exact fetch는 요청 된 행 수 이상을 반환합니다 .'.게시하기 전에 테스트 - 좋은 개념! :-) – mathguy

+0

@mathguy : 예! 나는 여기에 내 시간을 고려하는 것에 대해 사용자에게 경고했다. –