2017-10-18 100 views
2

我想知道是否有可能用另一個字符串加位置替換特定字符串而不使用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

我覺得這是有可能實現它的Wi第一行操作(也許是正則表達式)。

+1

是。可能與'REGEXP_INSTR','REGEXP_REPLACE'和'LEVEL'組合。 –

+0

是一個遞歸的cte好嗎?或者你更喜歡只有一個班輪:)? –

+0

@VamsiPrabhala隨時發佈您的解決方案:)一行優雅的解決方案是首選,但不是必要的:) – lad2025

回答

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 
+0

如果你對錶演感興趣,你可能仍然想嘗試這兩種方式。「模式」條款非常慢,但(1)也許你沒有很多數據,所以你不在乎; (2)在任何情況下,唯一可以確定的方法是通過測試**你的**數據,而不是其他人的數據。 – mathguy

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 
+0

+1這個解決方案基本上是正確的。遞歸CTE導致循環違例,可以通過向遞歸CTE添加CYCLE子句來解決該問題。另外,不需要使用「計數」來切斷遞歸;我在答案中展示了一種方法。但總體而言,解決方案很好。我將編輯答案以添加CYCLE子句。 – mathguy

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 
+0

感謝您的輸入。將它與'MODEL'結合起來效果非常好:) – lad2025

相關問題