Как добавить новые элементы в коллекцию без цикла?
Есть тестовая таблица. И есть прототип функции, которая должна дополнять коллекцию новыми элементами из различных таблиц.
create table tab (grp, nam, val) as
select 'grp'||(mod (rownum, 3)+1), 'name'||rownum, 'value'||rownum
from dual connect by level<=9
/
create or replace function addList (l tblt, grp varchar2) return tblt as
cursor cur (grp varchar2) is
select objt (grp, nam, val)
from tab where grp = cur.grp;
ret tblt := l;
tmp tblt;
begin
open cur (grp);
fetch cur bulk collect into tmp;
for i in 1..tmp.count loop
ret.extend;
ret(ret.last) := tmp(i);
end loop;
return ret;
end;
/
После получения новых записей в fetch, добавляю их к существующей колекции в цикле for-loop. Думаю, что есть более лаконичный способ без цикла.
Как можно добавить новые записи к существующей колекции без цикла?
В текущем виде, функция работает и даёт желаемый результат:
var rc refcursor
declare
tbl tblt := tblt (objt ('grp0', 'name0', 'value0'));
begin
tbl := addList (tbl, 'grp2');
open :rc for select * from table (tbl);
end;
/
+------+-------+--------+
| GRP | NAME | VALUE |
+------+-------+--------+
| grp0 | name0 | value0 |
| grp2 | name1 | value1 |
| grp2 | name4 | value4 |
| grp2 | name7 | value7 |
+------+-------+--------+
Ответы (1 шт):
Самое простое, добавить новые записи PL/SQL оператором MULTISET UNION:
create or replace function addList2 (old tblt, grp varchar2) return tblt as
cursor cur (grp varchar2) is
select objt (grp, nam, val)
from tab where grp = cur.grp
order by grp, nam;
new tblt;
begin
open cur (grp);
fetch cur bulk collect into new;
return (old multiset union all new);
end;
/
Также можно сразу объединить новые элементы с существующей колекцией добавив её в SQL запросе оператором объединения таблиц UNION ALL. Так будет возможность отсортировать результирующую коллекцию:
create or replace function addList1 (old tblt, grp varchar2) return tblt as
cursor cur (old tblt, grp varchar2) is
select objt (grp, nam, val) from (
select grp, nam, val
from tab where grp = cur.grp
union all
select * from table (old) s
) order by grp, nam;
ret tblt;
begin
open cur (old, grp);
fetch cur bulk collect into ret;
close cur;
return ret;
end;
/
Оба способа дадут желемый результат:
declare
tbl tblt := tblt (objt ('grp0', 'name0', 'value0'));
begin
tbl := addList1 (tbl, 'grp1');
tbl := addList2 (tbl, 'grp2');
open :rc for select * from table (tbl);
end;
/
GRP NAME VALUE
---- ---------------- ----------------
grp0 name0 value0
grp1 name3 value3
grp1 name6 value6
grp1 name9 value9
grp2 name1 value1
grp2 name4 value4
grp2 name7 value7