2017-08-24 63 views
2

我使用的是Oracle 11g,並且無法根據其他表中提到的位置替換多個字符。例如:Oracle SQL將不同位置的多個字符替換

表1

PRSKEY POSITION CHARACTER 
    123  3   ć 
    123  9   ć 

表2

PRSKEY NAME 
    123 Becirovic 

我不得不更換NAME表2Bećirović。 我試過regexp_replace但這個功能不能提供更多的1位置,有沒有簡單的方法來解決這個問題?

+0

我認爲在這樣做,你就需要讓你的串入一個記錄所有應用替換規則(2任何機會你上面的例子)。我沒有辦法做到這一點。我們可以問問你是如何結束這個問題的? –

+0

我認爲最好的方法是一個函數。你可以在環境中創建功能嗎? – pOrinG

+0

@TimBiegeleisen我會加入表格,添加'group by'並添加'LISTAGG()'函數(對於MySQL來說也是GROUP_CONCAT)。需要訂購小組成員並剪切字符串以獲得多個部分。應該工作,但查詢會很棘手。更容易引入功能。 – StanislavL

回答

0

簡單的解決方案使用光標...

create table t1 (
    prskey int, 
    pos int, 
    character char(1) 
); 

create table t2 
(
    prskey int, 
    name varchar2(100) 
); 

insert into t1 values (1, 1, 'b'); 
insert into t1 values (1, 3, 'e'); 

insert into t2 values (1, 'dear'); 


begin 
    for t1rec in (select * from t1) loop  
    update t2 
    set name = substr(name, 1, t1rec.pos - 1) || t1rec.character || substr(name, t1rec.pos + 1, length(name) - t1rec.pos) 
    where t2.prskey = t1rec.prskey; 
    end loop; 
end; 
/
+0

Thanx,完美的作品! – Erwin

+0

@Erwin歡迎你:)有我的啤酒 –

+0

我做了@Radim Baca ;-)。快速問題:有沒有辦法將這個光標包裝到存儲過程中? – Erwin

0

我寧願通過PL/SQL的方式,但在你的標籤只有 'SQL',所以我做了這個怪物:

with t as (
    select 123 as id, 3 as pos, 'q' as new_char from dual 
    union all 
    select 123 as id, 6 as pos, 'z' as new_char from dual 
    union all 
    select 123 as id, 9 as pos, '1' as new_char from dual 
    union all 
    select 456 as id, 1 as pos, 'A' as new_char from dual 
    union all 
    select 456 as id, 4 as pos, 'Z' as new_char from dual 
), 
t1 as (
    select 123 as id, 'Becirovic' as str from dual 
    union all 
    select 456 as id, 'Test' as str from dual 
)      
select listagg(out_text) within group (order by pos) 
from( 
    select id, pos, new_char, str, prev, substr(str,prev,pos-prev)||new_char as out_text 
    from(
    select id, pos, new_char, str, nvl(lag(pos) over (partition by id order by pos)+1,1) as prev 
    from (
     select t.id, pos, new_char, str 
     from t, t1 
     where t.id = t1.id 
    ) q 
) a 
) w 
group by id 

結果:

Beqirzvi1 
AesZ 
1

這裏是另一種方式來做到這一點。

with tab1 as (select 123 as prskey, 3 as position, 'ć' as character from dual 
      union select 123, 9, 'ć' from dual), 
    tab2 as (select 123 as prskey, 'Becirovic' as name from dual) 
select listagg(nvl(tab1.character, namechar)) within group(order by lvl) 
from 
    (select prskey, substr(name, level, 1) as namechar, level as lvl 
    from tab2 
    connect by level <= length(name) 
) splitname 
left join tab1 on position = lvl and tab1.prskey = splitname.prskey 
; 
+0

真的很好sollution –