2014-09-02 170 views
0

我在PL/SQL嵌套表的要求如下:嵌套表元素賦值

我有一個嵌套表集合類型聲明,我填充基於從表中查找的元素。 如果查找產生多行(多個代碼值),則將所有這些多個值添加到嵌套表中並繼續。這裏是我卡住的地方。 我無法在異常中增加父級計數器「indx」來處理這些多行。由於我不是,它只會將最新數據存儲在嵌套表中,而不是全部。

declare 
TYPE final_coll_typ IS TABLE OF varchar2(100); 

l_final_coll final_coll_typ; 

MULTI_FETCH EXCEPTION; 
PRAGMA EXCEPTION_INIT(MULTI_FETCH, -1422); -- this is an ora error for exact fetch returns more than the required number of rows 

begin 

for indx in 1..<count> loop 

    <some processing logic here> 
    select code into l_final_coll(indx) from lookup_tbl where <some filter>; 
    exception 
    when MULTI_FETCH then 
      for p in (select code from lookup_tbl where <some filter>) 
      loop 
          l_final_coll(indx) := p.code; 
          dbms_output.put_line(l_final_coll(indx)); 
         end loop; 
         continue; -- this is for further processing after the loop 

end loop; 
end; 

可以說,計數器indx的第一次迭代只產生一行代碼數據。它存儲在l_final_coll(indx)中。 可以說下一代indx主for循環產生2行代碼值。我的想法是捕捉異常(ORA-01422),並在現有的嵌套表中不斷添加這兩個代碼值。

所以,實際上,我的嵌套表現在它的元素中應該有3個代碼值。但是,目前,我只能得到它填充其中2個(從第一次更新的單個值和下一個的最新值)

任何指針將不勝感激我如何能夠實現這一點。

PS:嘗試操縱計數器變量indx和p。但是,顯然pl/sql不允許它用於「for循環」。

回答

2

你並不需要做一個選擇,只是一些使用遊標循環入手,並追加到集合(你不得不初始化):

declare 
    type final_coll_typ is table of varchar2(100); 
    l_final_coll final_coll_typ; 
begin 
    l_final_coll := final_coll_typ(); 
    for indx in 1..<count> loop 

    <some processing logic here> 

    for p in (select code from lookup_tbl where <some filter>) loop 
     l_final_coll.extend(1); 
     l_final_coll(l_final_coll.count) := p.code; 
    end loop; 
    end loop; 

    dbms_output.put_line('Final size: ' || l_final_coll.count); 
end; 
/

對於每個發現行但是遊標,集合被擴展1(這不是非常有效),並且遊標值被放入最後的空行中;這是從目前的count找到的。

作爲演示,如果我創建一個虛擬表有重複的值:

create table lookup_tbl(code varchar2(100)); 
insert into lookup_tbl values ('Code 1'); 
insert into lookup_tbl values ('Code 2'); 
insert into lookup_tbl values ('Code 2'); 
insert into lookup_tbl values ('Code 3'); 

...然後用特定的計數器和過濾:

declare 
    type final_coll_typ is table of varchar2(100); 
    l_final_coll final_coll_typ; 
begin 
    l_final_coll := final_coll_typ(); 
    for indx in 1..3 loop 
    for p in (select code from lookup_tbl where code = 'Code ' || indx) loop 
     l_final_coll.extend(1); 
     l_final_coll(l_final_coll.count) := p.code; 
    end loop; 
    end loop; 

    dbms_output.put_line('Final size: ' || l_final_coll.count); 
end; 
/

...我得到:

anonymous block completed 
Final size: 4 

作爲一個稍微COM可以將所有匹配的數據批量收集到一個臨時集合中,然後循環以將這些值附加到實際集合中。例如:

declare 
    type final_coll_typ is table of varchar2(100); 
    l_final_coll final_coll_typ; 
    l_tmp_coll sys.dbms_debug_vc2coll; 
begin 
    l_final_coll := final_coll_typ(); 
    for indx in 1..<count> loop 

    <some processing logic here> 

    select code bulk collect into l_tmp_coll from lookup_tbl where <some filter>; 

    for cntr in 1..l_tmp_coll.count loop 
     l_final_coll.extend(1); 
     l_final_coll(l_final_coll.count) := l_tmp_coll(cntr); 
    end loop; 
    end loop; 
end; 
/

可能有更快的方法來組合兩個集合,但我不知道其中之一。批量收集必須放入模式級收集類型,因此您不能使用本地final_coll_typ。您可以創建自己的模式級別類型,然後將其用於臨時和最終收集變量;但我用了一個內置的sys.dbms_debug_vc2coll,它被定義爲table of varchar2(1000)

作爲演示,以上述相同的表/數據,以及相同的具體數量和過濾器:

declare 
    type final_coll_typ is table of varchar2(100); 
    l_final_coll final_coll_typ; 
    l_tmp_coll sys.dbms_debug_vc2coll; 
begin 
    l_final_coll := final_coll_typ(); 
    for indx in 1..3 loop 

    select code bulk collect into l_tmp_coll 
    from lookup_tbl where code = 'Code ' || indx; 

    for cntr in 1..l_tmp_coll.count loop 
     l_final_coll.extend(1); 
     l_final_coll(l_final_coll.count) := l_tmp_coll(cntr); 
    end loop; 
    end loop; 

    dbms_output.put_line('Final size: ' || l_final_coll.count); 
end; 
/

...我再次得到:

anonymous block completed 
Final size: 4 
+0

感謝許多選項。你給的第一個選項是整潔的...不知道爲什麼我沒有想到它......呃! – Casey 2014-09-04 15:29:12