Oracle SQL替换不同位置的多个字符

Oracle SQL替换不同位置的多个字符,sql,oracle,Sql,Oracle,我使用的是Oracle11g,根据不同表中提到的位置替换多个字符时遇到问题。例如: 表1 表2 我必须将表2中的名称替换为ćirović。 我尝试过regexp_replace,但该函数不提供替换多于1个位置,有没有简单的方法修复此问题 我更喜欢通过PL/SQL实现,但在您的标记中只有“SQL”,所以我制作了这个怪物: with t as ( select 123 as id, 3 as pos, 'q' as new_char from dual union all select

我使用的是Oracle11g,根据不同表中提到的位置替换多个字符时遇到问题。例如:

表1

表2

我必须将表2中的名称替换为ćirović。
我尝试过regexp_replace,但该函数不提供替换多于1个位置,有没有简单的方法修复此问题

我更喜欢通过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

这里有另一种方法

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
;

使用光标的简单解决方案

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;
/

我认为要有机会做到这一点,您需要将字符串放入一个记录中,并使用上面示例中所有适用的替换规则2。我看不出有什么办法。我们可以问一下你是如何解决这个问题的吗?我认为最好的方法是函数。你能在环境中创建函数吗?@TimBiegeleisen我会加入表,添加group by并为MySQL添加LISTAGG函数,同样是group_CONCAT。需要对组成员进行排序,并将字符串切割成多个片段。应该可以,但查询会很棘手。更容易引入函数。@StanislavL是的,我想象过这样的事情,然后感到沮丧。我的感觉是数据模型应该改变,而不是执行这样的SQL操作。快速提问:有没有办法将此游标包装到存储过程中?@Erwin当然,您对该过程有什么具体的参数吗?老实说,我不知道我是需要一个过程还是一个函数。我给出的示例有一个没有特殊字符的名称,该名称必须转换为具有特殊字符的名称。因此,我希望有一个过程或函数能够更好地根据PRSKEY值自动返回具有特殊字符的值。
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
;
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;
/