как заменить несколько строк вместе в Oracle

У меня есть строка, полученная из таблицы, например "не могу заплатить{1}, так как ваш платеж{2}должен {3}". Я хочу заменить {1} некоторым значением, {2} некоторым значением и {3} некоторым значением.

Можно ли заменить все 3 в одной функции замены? или есть ли способ напрямую написать запрос и получить замененное значение? Я хочу заменить эти строки в хранимой процедуре Oracle, исходная строка исходит из одной из моих таблиц. Я просто делаю выбор в этой таблице.

а затем я хочу заменить значения {1},{2},{3} из этой строки на другое значение, которое у меня есть из другой таблицы


person RBS    schedule 17.09.2008    source источник
comment
Возможный дубликат множественной функции REPLACE в Oracle   -  person Joaquinglezsantos    schedule 06.11.2017


Ответы (5)


Хотя это не один вызов, вы можете вложить replace() вызовов:

SET mycol = replace( replace(mycol, '{1}', 'myoneval'), '{2}', mytwoval)
person hamishmcn    schedule 17.09.2008
comment
Во втором mytwoval отсутствуют одинарные кавычки? - person Simon The Cat; 06.10.2014
comment
@SimonTheCat Вы правы! (Если mytwoval не был переменной) - person hamishmcn; 09.10.2014

Если есть много переменных для замены, и они есть в другой таблице, и если количество переменных является переменным, вы можете использовать рекурсивный 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

person Florin Ghita    schedule 18.02.2015
comment
Псевдонимы в предложении WITH поддерживаются, начиная с Oracle 11gR2. - person Stephan; 28.05.2015
comment
IMH, это отличный ответ, потому что он касается точки, которая, к сожалению, была лишь косвенно упомянута в вопросе, а именно позволяет обновлять замененные термины без редактирования фактического запроса (что является полезным сценарием в контролируемой среде). - person Neil; 28.01.2016

Если число заменяемых значений слишком велико или вам нужно иметь возможность легко его поддерживать, вы также можете разделить строку, использовать таблицу словаря и, наконец, агрегировать результаты

В приведенном ниже примере я предполагаю, что слова в вашей строке разделены пробелами, а количество слов в строке не будет больше 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
person Ricardo Arnold    schedule 15.02.2016
comment
Это отличное использование предложения WITH и похвала за реализацию решения только для SQL, но результат по-прежнему довольно сложен (для некоторых из нас) для анализа! Кажется, это работает хорошо, но если бы я реализовал в своем коде, я бы не попросил коллегу проверить его на правильность. Они бы меня расстреляли! :-) - person StewS2; 07.03.2018

Давайте напишем тот же образец только в виде 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);
person Olc    schedule 08.11.2018

Если вы делаете это внутри выбора, вы можете просто собрать его вместе, если ваши значения замены являются столбцами, используя конкатенацию строк.

person Mitchel Sellers    schedule 17.09.2008