Oracle で複数の文字列をまとめて置換する方法
質問
「支払い期限が {3} のため、支払いができません{1}。{2}」というようなテーブルからの文字列があります。{1} を何らかの値、{2} を何らかの値、{3} を何らかの値に置き換えたいと考えています。
1 つの置換機能で 3 つすべてを置換することは可能ですか?それともクエリを直接記述して、置換された値を取得する方法はありますか?Oracle ストアド プロシージャ内のこれらの文字列を置き換えたいです。元の文字列はテーブルの 1 つから取得されており、そのテーブルで選択を行っているところです。
次に、その文字列の {1}、{2}、{3} の値を、別のテーブルの他の値に置き換えたいと考えています。
解決
1 回の呼び出しではありませんが、ネストすることができます。 replace()
呼び出し:
SET mycol = replace( replace(mycol, '{1}', 'myoneval'), '{2}', mytwoval)
他のヒント
置換する変数が多数あり、それらが別のテーブルにあり、変数の数が可変である場合は、再帰的 CTE を使用して変数を置換できます。以下に例を示します。テーブル fg_rulez には、文字列とその置換を入れます。テーブル fg_data には入力文字列があります。
set define off;
drop table fg_rulez
create table fg_rulez as
select 1 id,'<' symbol, 'less than' text from dual
union all select 2, '>', 'great than' from dual
union all select 3, '$', 'dollars' from dual
union all select 4, '&', 'and' from dual;
drop table fg_data;
create table fg_Data AS(
SELECT 'amount $ must be < 1 & > 2' str FROM dual
union all
SELECT 'John is > Peter & has many $' str FROM dual
union all
SELECT 'Eliana is < mary & do not has many $' str FROM dual
);
WITH q(str, id) as (
SELECT str, 0 id
FROM fg_Data
UNION ALL
SELECT replace(q.str,symbol,text), fg_rulez.id
FROM q
JOIN fg_rulez
ON q.id = fg_rulez.id - 1
)
SELECT str from q where id = (select max(id) from fg_rulez);
それで、シングル replace
.
結果:
amount dollars must be less than 1 and great than 2
John is great than Peter and has many dollars
Eliana is less than mary and do not has many dollars
変数の代わりに用語記号が使われたのは、 この重複した質問。
オラクル 11gR2
置換する値の数が大きすぎる場合、またはそれを簡単に管理できるようにする必要がある場合は、文字列を分割し、ディクショナリ テーブルを使用して、最後に結果を集計することもできます。
以下の例では、文字列内の単語が空白で区切られており、文字列内の単語数が 100 (ピボット テーブルの基数) を超えないと仮定しています。
with Dict as
(select '{1}' String, 'myfirstval' Repl from dual
union all
select '{2}' String, 'mysecondval' Repl from dual
union all
select '{3}' String, 'mythirdval' Repl from dual
union all
select '{Nth}' String, 'myNthval' Repl from dual
)
,MyStrings as
(select 'This is the first example {1} ' Str, 1 strnum from dual
union all
select 'In the Second example all values are shown {1} {2} {3} {Nth} ', 2 from dual
union all
select '{3} Is the value for the third', 3 from dual
union all
select '{Nth} Is the value for the Nth', 4 from dual
)
,pivot as (
Select Rownum Pnum
From dual
Connect By Rownum <= 100
)
,StrtoRow as
(
SELECT rownum rn
,ms.strnum
,REGEXP_SUBSTR (Str,'[^ ]+',1,pv.pnum) TXT
FROM MyStrings ms
,pivot pv
where REGEXP_SUBSTR (Str,'[^ ]+',1,pv.pnum) is not null
)
Select Listagg(NVL(Repl,TXT),' ') within group (order by rn)
from
(
Select sr.TXT, d.Repl, sr.strnum, sr.rn
from StrtoRow sr
,dict d
where sr.TXT = d.String(+)
order by strnum, rn
) group by strnum
同じサンプルを CTE のみとして作成してみましょう。
with fg_rulez as (
select 1 id,'<' symbol, 'less than' text from dual
union all select 2, '>', 'greater than' from dual
union all select 3, '$', 'dollars' from dual
union all select 4, '+', 'and' from dual
), fg_Data AS (
SELECT 'amount $ must be < 1 + > 2' str FROM dual
union all
SELECT 'John is > Peter + has many $' str FROM dual
union all
SELECT 'Eliana is < mary + do not has many $' str FROM dual
), q(str, id) as (
SELECT str, 0 id
FROM fg_Data
UNION ALL
SELECT replace(q.str,symbol,text), fg_rulez.id
FROM q
JOIN fg_rulez
ON q.id = fg_rulez.id - 1
)
SELECT str from q where id = (select max(id) from fg_rulez);
これを選択内で行う場合、置換値が列の場合は、文字列連結を使用して結合することができます。