2017-07-24 144 views
0

這是我需要做的一個簡單例子。實際上,我想通過使用plsql中的遊標來應對來自另一個表的應答來更新一個表中的值。如何通過應對來自plsql中的另一個表來更新一個表中的值?

予取表f和表B作爲兩個實例:

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



b= 
7|Nataly                                                
9|Alfred 

,其中I需要插入在第一的B的絲束線路f的兩行:

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的初學者,如果能幫助我,我將非常感激。

+0

PL/SQL,當然,與Oracle,MySQL的不使用的語言。我編輯了你的標籤。 –

+0

@ O.Jones謝謝 – tierrytestu

+0

爲什麼你需要這樣做?這是你的家庭作業嗎?如果是這樣,你應該在解決方案中展示什麼?我問,因爲它不是經常需要在現實世界中完成的事情(即,用表2中的X行覆蓋表1中第一個X行的內容) - 通常它會根據某種類型合併行連接列(例如,一個ETL過程更新客戶的詳細信息等) – Boneist

回答

0

您的過程編譯,但有錯誤; 編譯後爲了看編譯錯誤 運行show errors;

變化open c_bopen 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; 
/
+0

非常感謝您的幫助,但是我需要複製所有的源桌子並把它們作爲目標表中的第一行,我給你的只是一個例子。 – tierrytestu

+0

這個解決方案並沒有給我預期的結果,它給了我一個只有兩行的數組:7 | Nataly 9 | Alfred – tierrytestu

+0

@tierrytestu所以你想複製所有行從源到目標?你的例子只顯示2行。 – fg78nc

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

非常感謝您的幫助,它是第一個給我一些好結果的解決方案,但在我的真實場景中,我有超過2行來自源表(b),所以此解決方案插入第一個和最後一個列, – tierrytestu

+0

@tierrytestu我不確定你的意思是「所以這個解決方案只插入第一列和最後一列」?如果您的問題中的示例與您的實際情況不匹配,則應更新您的問題以更準確。我們毫無意義地給你一個問題的答案,而這個問題不是你真正希望我們回答的問題! – Boneist

+0

我真的很抱歉,這個解決方案只爲我插入第一行和最後一行,而不是所有的行, – tierrytestu

相關問題