Sql 用另一个字符串加上相应的位置替换字符串

Sql 用另一个字符串加上相应的位置替换字符串,sql,oracle,replace,oracle11g,oracle12c,Sql,Oracle,Replace,Oracle11g,Oracle12c,我想知道是否可以用另一个字符串加位置替换特定字符串,而不使用PL/SQL块循环、用户定义的函数/存储过程以及函数构造 此处:st->pos\u num 输入: "aa bbb st cccc dddd st eeeeeeeeeee ffff g st g h i st j k l m st" 输出: "aa bbb pos_1 cccc dddd pos_2 eeeeeeeeeee ffff g pos_3 g h i pos_4 j k l m pos_5" pos_1 post aa b

我想知道是否可以用另一个字符串加位置替换特定字符串,而不使用PL/SQL块循环、用户定义的函数/存储过程以及函数构造

此处:st->pos\u num

输入:

"aa bbb st cccc dddd st eeeeeeeeeee ffff g st g h i st j k l m st"
输出:

"aa bbb pos_1 cccc dddd pos_2 eeeeeeeeeee ffff g pos_3 g h i pos_4 j k l m pos_5"
pos_1 post aa bbb pos_2 cccc dddd pos_3 ee ffff g pos_4 g h i pos_5 j k l m pos_6

我觉得可以通过一行操作(可能是regex)实现它。

递归cte方法

with cte(string,col,cnt,repl) as
(select string,1,regexp_count(string,'st'),regexp_replace(string,'st','pos_'||to_char(1),1,1) as repl
 from test
 union all
 select string,col+1,cnt,regexp_replace(repl,'st','pos_'||to_char(col+1),1,1) as repl
 from cte
 --join it to the original table if there are multiple rows, on string column.
 where col<cnt
)
cycle col set cycle to 1 default 0
select string,repl
from cte
where cnt=col

下面是一个使用递归CTE的稍微不同的解决方案。只有当st被空格或字符串的开头或结尾包围时,它才会查找st

with
  inputs ( str ) as (
    select 'aa bbb st sccc dddd st eee fff g st g h i st j k l m st' from dual
    union all
    select 'st abc st st st where st is not st'                      from dual
    union all
    select 'post st stop postal'                                     from dual
  ),
  r ( lvl, str, new_str ) as (
    select  1, str, str
      from  inputs
    union all
    select  lvl + 1, str, 
            regexp_replace(new_str, '( |^)st( |$)', '\1pos_' || lvl || '\2', 1, 1)
      from  r
      where regexp_like(new_str, '( |^)(st)( |$)')
  )
select str, new_str
from   r
where  not regexp_like(new_str, '( |^)(st)( |$)')
;

STR                                                      NEW_STR
-------------------------------------------------------  ----------------------------------------------------------------------
post st stop postal                                      post pos_1 stop postal
aa bbb st sccc dddd st eee fff g st g h i st j k l m st  aa bbb pos_1 sccc dddd pos_2 eee fff g pos_3 g h i pos_4 j k l m pos_5
st abc st st st where st is not st                       pos_1 abc pos_2 pos_3 pos_4 where pos_5 is not pos_6
使用示范条款:

输出:

"aa bbb pos_1 cccc dddd pos_2 eeeeeeeeeee ffff g pos_3 g h i pos_4 j k l m pos_5"
pos_1 post aa bbb pos_2 cccc dddd pos_3 ee ffff g pos_4 g h i pos_5 j k l m pos_6

对可能与REGEXP_INSTR、REGEXP_REPLACE和LEVEL组合在一起。递归cte可以吗?或者您只喜欢一行:?@VamsiPrabhala请随意发布您的解决方案:首选一行优雅的解决方案,但不是必需的:您是否需要替换字符串,即使它位于较长的单词内?那么,在您的示例中,是否将输入字符串“post”替换为“popos_1”?如果不是-如果“st”仅在它是一个独立单词时才被替换,那么规则是什么?例如:如果它是一个复合词的一部分,比如“st jack”,该怎么办?@mathguy只包含完整的单词,所以st jack不应该受到影响。应更换st。+1解决方案基本正确。递归CTE导致循环冲突,可以通过向递归CTE添加cycle子句来解决。而且,不需要使用计数来切断递归;我在回答中展示了一种方法。但总的来说,解决方案是好的。我将编辑答案以添加循环子句。谢谢您的输入。将它与模型结合使用效果非常好:如果您对性能感兴趣,您可能仍然希望尝试这两种方法。示范条款的速度是出了名的慢;但是1也许你没有太多的数据,所以你不在乎;在任何情况下,唯一确定的方法是测试你的数据,而不是其他人的数据。