用循环中的多个字符替换字符串中的一个字符 - ORACLE

Posted

技术标签:

【中文标题】用循环中的多个字符替换字符串中的一个字符 - ORACLE【英文标题】:Replace One character in string with multiple characters in loop - ORACLE 【发布时间】:2020-11-27 18:29:17 【问题描述】:

我有一种情况,说一个字符串有一个可替换的字符..例如..

Thi[$] is a strin[$] I am [$]ew to Or[$]cle

现在我需要将 [$] 替换为 s,g,n,a 分别...

我该怎么做?请帮忙。

【问题讨论】:

[$] 看起来像 verilog - 你在说什么语言?你已经尝试过什么? 单单这句话,就有办法了。如果您希望将所有单词替换为相应的字符,则无法在 sql 中完成。您必须使用 python 或其他语言进行自然语言处理 @JimMacaulay - 至少在 Oracle 中它可以在 SQL 中完成。我怀疑其他风格的 SQL 至少会支持my solution。 【参考方案1】:

有一个特殊的PL/SQL函数UTL_LMS.FORMAT_MESSAGE:

您可以在INLINE pl/sql function 中使用它:

with function format(
    str in varchar2
   ,s1 in varchar2 default null
   ,s2 in varchar2 default null
   ,s3 in varchar2 default null
   ,s4 in varchar2 default null
   ,s5 in varchar2 default null
   ,s6 in varchar2 default null
   ,s7 in varchar2 default null
   ,s8 in varchar2 default null
   ,s9 in varchar2 default null
   ,s10 in varchar2 default null
   ) return varchar2 
   as
begin
   return utl_lms.format_message(replace(str,'[$]','%s'),s1,s2,s3,s4,s5,s6,s7,s8,s9,10);
end;
select format('Thi[$] is a strin[$] I am [$]ew to Or[$]cle', 's','g','n','a') as res
from dual;

结果:

RES
-------------------------------------
This is a string I am new to Oracle

【讨论】:

【参考方案2】:

这是一个使用递归 WITH 子句的手动解决方案,以及 INSTR 和 SUBSTR 函数来切分字符串并在每个接合点注入相关字母。

with rcte(str, sigils, occ) as (
  select 'Thi[$] is a strin[$] I am [$]ew to Or[$]cle' as str
          , 'sgna' as sigils
          , 0 as occ 
  from dual
  union all
  select substr(str, 1, instr(str,'[$]',1,1)-1)||substr(sigils, occ+1, 1)||substr(str, instr(str,'[$]',1,1)+3) as str
         , sigils
         , occ+1 as occ
  from rcte
  where occ <= length(sigils)
)
select * 
from rcte
where occ = length(sigils)

这里是a working demo on db<>fiddle。

不过,@sayanm 似乎提供了a neater solution。

【讨论】:

如果我不能使用内联 pl/sql,我会在这种情况下使用 model 子句。它应该是一个更快的解决方案【参考方案3】:

考虑这种方法,它可以让查找值基于表。见里面的cmets。使用占位符作为分隔符将原始字符串分成几行。然后使用 listagg 将行重新组合在一起,将其顺序​​加入到查找表中。

表格驱动,使用任意数量的占位符。当然,顺序很重要,就像其他答案一样。

-- First CTE just sets up source data
WITH tbl(str) AS (
  SELECT 'Thi[$] is a strin[$] I am [$]ew to Or[$]cle' FROM dual
),
-- Lookup table.  Does not have to be a CTE here, but a normal table
-- in the database.
tbl_sub_values(ID, VALUE) AS (
  SELECT 1, 's' FROM dual UNION ALL
  SELECT 2, 'g' FROM dual UNION ALL
  SELECT 3, 'n' FROM dual UNION ALL
  SELECT 4, 'a' FROM dual
),
-- Split the source data using the placeholder as a delimiter
tbl_split(piece_id, str) AS (
  SELECT LEVEL AS piece_id, REGEXP_SUBSTR(t.str, '(.*?)(\[\$\]|$)', 1, LEVEL, NULL, 1) 
  FROM tbl T
  CONNECT BY LEVEL <= REGEXP_COUNT(t.str, '[$]') + 1
)
-- select * from tbl_split;
-- Put the string back together, joining with the lookup table
SELECT LISTAGG(str||tsv.value) WITHIN GROUP (ORDER BY piece_id) STRING
FROM tbl_split ts
  LEFT JOIN tbl_sub_values tsv
    ON ts.piece_id = tsv.id;

STRING                                                                          
--------------------------------------------------------------------------------
This is a string I am new to Oracle     

【讨论】:

以上是关于用循环中的多个字符替换字符串中的一个字符 - ORACLE的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别