如何通过从plsql中的另一个表中复制来更新一个表中的值?

时间:2017-07-24 21:19:30

标签: oracle plsql

这是我需要做的一个简单例子。事实上,我希望通过在plsql中使用游标从另一个表中复制它来更新一个表中的值。

我把表f和表b作为两个例子:

f= 
1|Thom                                                                                                                                                                                              
2|Bob                                                                                                                                                                                               
3|Steven                                                                                                                                                                                            
5|Arthur



b= 
7|Nataly                                                                                                                                                                                              
9|Alfred

,我需要在前两行中插入b&#39的拖曳线:

create table f (a number, b varchar2(10));

insert into f values (1,'Thom');
insert into f values (2,'Bob');
insert into f values (3,'Steven');
insert into f values (5,'Arthur');
commit;


create table b (c number, d varchar2(10));

insert into b values (7,'Nataly');
insert into b values (9,'Alfred');

commit;
create or replace procedure wco as

  cursor c_f is 
    select a,b from f  for update;
    v_a f.a%type;
    v_b f.b%type;

  cursor c_b is 
    select c,d from b;
    v_c b.c%type;
    v_d b.d%type;

begin
  open c_f;
    open c_b
      loop
        fetch c_f into v_a, v_b;
        exit when c_f%ROWCOUNT=c_b%RROWCOUNT;
        update f set a=v_c and b=v_d where current of c_f;
      end loop;
    close c_d:
  close c_f;
end;
/

exec wco;

select * from f;

drop table f;

预期结果(我希望有什么):

7|Nataly                                                                                                                                                                                              
9|Alfred                                                                                                                                                                                              
3|Steven                                                                                                                                                                                            
5|Arthur 

但我现在所拥有的(因此)是:

1|Thom                                                                                                                                                                                              
2|Bob                                                                                                                                                                                               
3|Steven                                                                                                                                                                                            
5|Arthur

我如何解决这个问题,我是PLSQL的初学者,如果你能帮助我,我将非常感激。

2 个答案:

答案 0 :(得分:0)

你的程序编译,但有错误; 为了看到编译错误 编译后运行show errors;

open c_b更改为open c_b;(最后缺少分号)

close c_d:更改为close c_b;(正确的名称是c_b和分号而不是冒号)

exit when c_f%ROWCOUNT=c_b%RROWCOUNT;更改为c_f%ROWCOUNT=c_b%ROWCOUNT;(错误%RROWCOUNT;

时退出

update f set a=v_c and b=v_d where current of c_f;这是错误的SQL语法。 应该是update table_name set column=value, column=value;

为变量提供描述性名称非常重要,因此理解逻辑会更容易。

据我所知,你只想从源表中复制第二行。

create table source_table (
    id number, 
    name varchar2(10));
/

insert into source_table values (1,'Thom');
insert into source_table values (2,'Bob');
insert into source_table values (3,'Steven');
insert into source_table values (5,'Arthur');
/

create table target_table (
       id number, 
       name varchar2(10));
/

insert into target_table values (7,'Nataly');
insert into target_table values (9,'Alfred');
/

create or replace procedure copy_tables  
AS
 begin
  FOR source_row IN (select id, name 
                  from source_table 
                  offset 2 rows)
    LOOP
      insert into target_table
       values(source_row.id, source_row.name);
    END LOOP;
end;
/

exec copy_tables;
/

select id, name from target_table;
/

答案 1 :(得分:0)

你不需要PL / SQL;它可以在一个MERGE语句中实现:

merge into f tgt 
  using (select coalesce(b1.id, f1.id) id, 
                coalesce(b1.name, f1.name) name, 
                f1.f_rowid 
         from   (select id, 
                        name, 
                        rowid f_rowid, 
                        row_number() over (order by id) rn 
                 from   f) f1 
                full outer join (select id, 
                                        name, 
                                        row_number() over (order by id) rn 
                                 from   b) b1 
                  on f1.rn = b1.rn) src 
    on (tgt.rowid = src.f_rowid) 
when matched then 
  update set tgt.id = src.id, 
             tgt.name = src.name 
  where tgt.id != src.id 
  or    tgt.name != src.name 
when not matched then 
  insert (tgt.id, tgt.name) 
  values (src.id, src.name);

有关测试详细信息,请参阅https://livesql.oracle.com/apex/livesql/file/content_FBPR7YCLFVWO7NGDXTLSP1R97.html(两个示例;目标表包含更多且行数少于源表的行。)

如果需要,可以将上述插入添加到过程中,例如:

create procedure populate_target_table as
begin
  merge into f tgt 
    using (select coalesce(b1.id, f1.id) id, 
                  coalesce(b1.name, f1.name) name, 
                  f1.f_rowid 
           from   (select id, 
                          name, 
                          rowid f_rowid, 
                          row_number() over (order by id) rn 
                   from   f) f1 
                  full outer join (select id, 
                                          name, 
                                          row_number() over (order by id) rn 
                                   from   b) b1 
                    on f1.rn = b1.rn) src 
      on (tgt.rowid = src.f_rowid) 
  when matched then 
    update set tgt.id = src.id, 
               tgt.name = src.name 
    where tgt.id != src.id 
    or    tgt.name != src.name 
  when not matched then 
    insert (tgt.id, tgt.name) 
    values (src.id, src.name);
end;
/