2015-01-13 133 views
0

我寫一包如下: -光標內的所有PLSQL

create or replace package body pack_name 
    is 

    cursor is cur_get_data(p_run_id) 
    is 
    select p_run_id run_id, 
    person_id , 
    emp_name 
    from abc; 


    TYPE demo_table_type IS TABLE OF get_demo_data%ROWTYPE; 

     demo_table       demo_table_type; 

    procedure demo_data(p_data_array  IN  demo_table_type) 
    is 

    cursor is cur_get_person(p_person_id number) 
    is 
    select tot_comp_annual 
    from xyz; 

    begin 

    FORALL j IN 1 .. p_data_array.COUNT SAVE EXCEPTIONS 
     insert  
     INTO table_bad (run_id, person_id,emp_name) 
    VALUES (p_data_array (j).run_id, 
          p_data_array (j).person_id, 
          p_data_array (j).emp_name); 


    end; 

現在的問題是,我想打開cur_get_person並傳遞我從p_data_array得到爲person_id(J).person_id和將該值插入table_bad的列annual_comp中。我怎樣才能做到這一點 ?

+2

與福爾,這是不可能的。據我所知,Forall只承認一次dml操作 – Aramillo

回答

2

最簡單的答案是不使用遊標。相反,請將xyz中的選擇建立到insert聲明中。一般來說,你應該避免在遊標循環中打開遊標;這就是聯結的目的。

CREATE OR REPLACE PACKAGE BODY pack_name IS 
    CURSOR cur_get_data (p_run_id NUMBER) IS 
     SELECT p_run_id run_id, person_id, emp_name FROM abc; 


    TYPE demo_table_type IS TABLE OF get_demo_data%ROWTYPE; 

    demo_table demo_table_type; 

    PROCEDURE demo_data (p_data_array IN demo_table_type) IS 
    BEGIN 
     FORALL j IN 1 .. p_data_array.COUNT SAVE EXCEPTIONS 
     INSERT INTO table_bad (run_id, 
           person_id, 
           emp_name, 
           tot_comp_annual) 
      SELECT p_data_array (j).run_id, 
        p_data_array (j).person_id, 
        p_data_array (j).emp_name, 
        tot_comp_annual 
      FROM xyz 
      WHERE xyz.person_id = p_data_array (j).person_id; 
    END; 
END; 
1

你可以不經由另外的集合(產生一個內部錯誤,除非我做錯事)指的是光標直接,甚至間接的。 Allan展示瞭如何將遊標查詢與集合結合使用,但是由於您似乎並沒有真正需要PL/SQL,所以我假設您只是在嘗試並試圖將事物以故意複雜的方式。所以這裏有一個方法來繼續這一主題,並使用你的光標:

procedure demo_data(p_data_array IN demo_table_type) is 

    cursor get_person_info is 
     select person_id, tot_comp_annual 
     from xyz; 

    type comp_table_type is table of xyz.tot_comp_annual%type 
     index by pls_integer; 
    comp_table comp_table_type; 

    type bad_table_type is table of table_bad%rowtype; 
    bad_table bad_table_type := bad_table_type(); 
    begin 

    -- intentioanlly convoluted, since the whole idea is; get all the 
    -- info into another PL/SQL table 
    for r in get_person_info loop 
     comp_table(r.person_id) := r.tot_comp_annual; 
    end loop; 

    -- merge the two existing tables into a third with all the columns 
    bad_table.extend(p_data_array.count); 
    for j in 1 .. p_data_array.count loop 
     bad_table(j).run_id := p_data_array(j).run_id; 
     bad_table(j).person_id := p_data_array(j).person_id; 
     bad_table(j).emp_name := p_data_array(j).emp_name; 
     if comp_table.exists(p_data_array(j).person_id) then 
     bad_table(j).tot_comp_annual := 
      comp_table(p_data_array(j).person_id); 
     end if; 
    end loop; 

    forall j in 1 .. bad_table.count save exceptions 
     insert into table_bad values bad_table(j); 

    end demo_data; 

此創建一個本地的PL/SQL表,所有的get_person_info行是批量提取到。你也不能直接在forall中使用。但是你可以擁有第三個基於你的目標表的PL/SQL表,並且從p_data_array和保存你的遊標數據的集合中填充它。這也簡化了forall,因爲您可以一次插入整行。

SQL Fiddle demo