OracleのREPLACE
関数を使用して、次のような文字列の値を置き換えています。
SELECT REPLACE('THE NEW VALUE IS #VAL1#','#VAL1#','55') from dual
したがって、これは1つの値を置き換えても問題ありませんが、20 +の場合、20 +のREPLACE
関数を使用する必要がありますか、またはより実用的なソリューションがあります。
すべてのアイデアを歓迎します。
このスレッドが古くてもGoogleで最初のものであるため、正規表現を使用して、ここで実装した関数と同等のOracleを投稿します。
入れ子になったreplace()よりもかなり速く、はるかにきれいです。
特定のテーブルの文字列列で文字列「a」、「b」、「c」を「d」に置き換えるには
select regexp_replace(string_col,'a|b|c','d') from given_table
これは、「or」演算子を使用したいくつかの静的パターンの正規表現に他なりません。
正規表現の特殊文字に注意してください!
結果に留意してください
SELECT REPLACE(REPLACE('TEST123','123','456'),'45','89') FROM DUAL;
123を456に置き換え、45を89に置き換えることができることを見つけます。同等の結果を持つ関数の場合、優先順位を複製する必要があります(つまり、同じ順序で文字列を置き換える)。
同様に、文字列「ABCDEF」を取得し、「ABC」を「123」に、「CDE」を「xyz」に置き換えるように指示する場合も、「123EF」または「ABxyzF」のどちらであるかを判断するために優先順位を考慮する必要があります。
要するに、入れ子になったREPLACEよりも単純なジェネリックを思い付くのは難しいでしょう(ただし、sprintfスタイルの関数のようなものは便利な追加機能です)。
Oracleで複数の文字列を一緒に置き換える方法 に対する受け入れられた答えは、ネストされたREPLACE
ステートメントの使用を示唆しており、より良い方法はないと思います。
これを多用する場合は、独自の関数を記述することを検討できます。
CREATE TYPE t_text IS TABLE OF VARCHAR2(256);
CREATE FUNCTION multiple_replace(
in_text IN VARCHAR2, in_old IN t_text, in_new IN t_text
)
RETURN VARCHAR2
AS
v_result VARCHAR2(32767);
BEGIN
IF( in_old.COUNT <> in_new.COUNT ) THEN
RETURN in_text;
END IF;
v_result := in_text;
FOR i IN 1 .. in_old.COUNT LOOP
v_result := REPLACE( v_result, in_old(i), in_new(i) );
END LOOP;
RETURN v_result;
END;
そして、次のように使用します:
SELECT multiple_replace( 'This is #VAL1# with some #VAL2# to #VAL3#',
NEW t_text( '#VAL1#', '#VAL2#', '#VAL3#' ),
NEW t_text( 'text', 'tokens', 'replace' )
)
FROM dual
これは、置き換えるトークンを含むテキストです
すべてのトークンが同じ形式('#VAL' || i || '#'
)である場合、パラメーターin_old
を省略して、代わりにループカウンターを使用できます。
これは古い投稿ですが、私は結局Peter Langの考えを使用し、同様の、しかしまだ異なるアプローチをしました。ここに私がやったことがあります:
CREATE OR REPLACE FUNCTION multi_replace(
pString IN VARCHAR2
,pReplacePattern IN VARCHAR2
) RETURN VARCHAR2 IS
iCount INTEGER;
vResult VARCHAR2(1000);
vRule VARCHAR2(100);
vOldStr VARCHAR2(50);
vNewStr VARCHAR2(50);
BEGIN
iCount := 0;
vResult := pString;
LOOP
iCount := iCount + 1;
-- Step # 1: Pick out the replacement rules
vRule := REGEXP_SUBSTR(pReplacePattern, '[^/]+', 1, iCount);
-- Step # 2: Pick out the old and new string from the rule
vOldStr := REGEXP_SUBSTR(vRule, '[^=]+', 1, 1);
vNewStr := REGEXP_SUBSTR(vRule, '[^=]+', 1, 2);
-- Step # 3: Do the replacement
vResult := REPLACE(vResult, vOldStr, vNewStr);
EXIT WHEN vRule IS NULL;
END LOOP;
RETURN vResult;
END multi_replace;
次に、私はこのようにそれを使用することができます:
SELECT multi_replace(
'This is a test string with a #, a $ character, and finally a & character'
,'#=%23/$=%24/&=%25'
)
FROM dual
これにより、任意の文字/文字列で任意の文字/文字列を使用できるようになります。
私は自分のブログにこれに関する投稿を書きました。
すべてのソース文字列と置換文字列が1文字の長さしかない場合、単にTRANSLATE
関数を使用できます。
SELECT translate('THIS IS UPPERCASE', 'THISUP', 'thisup')
FROM DUAL
詳細については、 Oracleドキュメント を参照してください。
パラメーターとしてvarchar2のテーブルを使用して、一般的な複数置換文字列Oracle関数を作成しました。 varcharは、tableの位置rownum値に置き換えられます。
例えば:
Text: Hello {0}, this is a {2} for {1}
Parameters: TABLE('world','all','message')
戻り値:
Hello world, this is a message for all.
タイプを作成する必要があります。
CREATE OR REPLACE TYPE "TBL_VARCHAR2" IS TABLE OF VARCHAR2(250);
機能は次のとおりです。
CREATE OR REPLACE FUNCTION FN_REPLACETEXT(
pText IN VARCHAR2,
pPar IN TBL_VARCHAR2
) RETURN VARCHAR2
IS
vText VARCHAR2(32767);
vPos INT;
vValue VARCHAR2(250);
CURSOR cuParameter(POS INT) IS
SELECT VAL
FROM
(
SELECT VAL, ROWNUM AS RN
FROM (
SELECT COLUMN_VALUE VAL
FROM TABLE(pPar)
)
)
WHERE RN=POS+1;
BEGIN
vText := pText;
FOR i IN 1..REGEXP_COUNT(pText, '[{][0-9]+[}]') LOOP
vPos := TO_NUMBER(SUBSTR(REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i),2, LENGTH(REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i)) - 2));
OPEN cuParameter(vPos);
FETCH cuParameter INTO vValue;
IF cuParameter%FOUND THEN
vText := REPLACE(vText, REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i), vValue);
END IF;
CLOSE cuParameter;
END LOOP;
RETURN vText;
EXCEPTION
WHEN OTHERS
THEN
RETURN pText;
END FN_REPLACETEXT;
/
使用法:
TEXT_RETURNED := FN_REPLACETEXT('Hello {0}, this is a {2} for {1}', TBL_VARCHAR2('world','all','message'));