2017-10-18 4 views
0

STRING内の複数の(連続した)水平スペースを単一の水平スペースに置き換えるFUNCTIONがあります。Oracle - String - 句読点書式設定関数

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が複数の(連続した)水平スペースを引き続き除去することが重要です。

たとえば、

出力は、私が使用したい'Hello (Marc)'

ルールはかなり基本的なものになるだろうSTR_ORIG = '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. 

*注:閉じた括弧の直後にカンマまたはフルストップがある場合、 'One HORIZONTAL SPACE'の代わりに 'No HORIZONTAL SPACE'ルールが使用されます。

私は、純粋な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

REGEXPを使用して、INSTRSUBSTRを使用するよりも、関数を書くことができます。

注:この関数は、同じ文字列内に複数のパターンが現れることは考慮しません。したがって、 "、"と "。"の両方が表示されても動作しません。このようなシナリオをカバーするには、必要なすべての変換コード、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

残念ながら、これは正常にコンパイルされますが、テストの結果、 'ORA-01422:exact fetchは要求された行数を超えて戻ります。投稿する前にテスト - どのような素晴らしいコンセプト! :-) – mathguy

+0

@mathguy:はい!私はここに私の時間を考えていることについてユーザーに警告しました.. –

関連する問題