2014-09-02 160 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