2017-10-18 91 views
0

我有一個FUNCTION,它用一個單獨的水平空間替換STRING中的多個(連續)水平空間;Oracle - 字符串 - 標點符號格式化函數

例如

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'

如果STR_ORIG = 'Hello.Marc'輸出將成爲'Hello. Marc'

如果STR_ORIG = 'Hello(Marc)'輸出將成爲'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. 

*注意:當在閉括號後面直接出現逗號或完全停止符時,而不是'One HORIZONTAL SPACE'規則,它將使用'No HORIZONTAL SPACE'規則。

我認爲FUNCTION是這個問題的最佳方法(我已經探索過使用純SQL(REG_EXP),但代碼開始變得相當混亂 - 主要是由於數據不一致)。另外,如果我想在將來添加其他規則(例如,強調下劃線的規則),我假設FUNCTION會更容易維護。不過,我一如既往接受專業人士的建議。

非常感謝提前。

回答

1

還有一個方法,我能想到的是使用associated array存儲模式和替換,而不是普通的SQL。然後在循環中應用每個字符串轉換。

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

您可以使用REGEXP編寫函數,而不是使用INSTR,SUBSTR

注意:該函數不考慮出現在同一個字符串中的多種類型的模式。所以如果「,」和「。」都出現,它將不起作用。因此,您可以自己編寫所有需要的轉換代碼,EXCEPTION來處理這些情況。我已經給出了關於如何完成的想法。您可能需要重寫IF THENCASE塊,因爲我在代碼爲PL/SQL的with子句中編碼。

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

不幸的是,這個編譯好,但經過測試,它會導致'ORA-01422:精確的讀取返回超過請求的行數'。張貼之前進行測試 - 多好的概念! :-) – mathguy

+0

@mathguy:是的!我提醒用戶關於考慮我在這裏的時間.. –