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

时间:2017-10-18 17:42:11

标签: sql oracle replace oracle11g oracle12c

我想知道是否可以在不使用PL / SQL块的情况下将特定字符串替换为另一个字符串加位置(循环,用户定义的函数/存储过程,带有函数构造......)。

此处:st - > pos_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"

DBFiddle

我觉得可以通过一行操作(可能是正则表达式)来实现它。

3 个答案:

答案 0 :(得分:2)

递归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

答案 1 :(得分:1)

这是使用递归CTE的略微不同的解决方案。它仅在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

答案 2 :(得分:0)

使用MODEL子句:

select m_1
from dual
model dimension by (0 as key)
measures (cast('st post aa bbb st cccc dddd st ee ffff g st g h i st j k l m st' 
                as varchar2(500)) as m_1 )
rules iterate (100) until(not regexp_like(m_1[0], '( |^)(st)( |$)'))
(m_1[0] = regexp_replace(m_1[0],
          '( |^)st( |$)','\1pos_'||to_char(ITERATION_NUMBER+1)||'\2',1,1));

<强> DBFiddle Demo

输出:

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