Как найти элемент ассоциативной коллекции по значению одного из атрибутов?
Допустим, загружаю данные в коллекцию с типм элементов ROWTYPE.
Как извлечь отдельные атрибуты элементов коллекции, если передавать id в качестве параметра без использования цикла?
create table emp (id number, name varchar2(20), age number);
insert into emp values(10,'Tom',20);
insert into emp values(20,'Nicole',30);
commit;
declare
TYPE emp_t IS TABLE OF emp%ROWTYPE INDEX BY PLS_INTEGER;
emp_tab emp_t;
begin
select id,name,age bulk collect into emp_tab from emp;
for idx in 1..emp_tab.count loop
dbms_output.put_line(emp_tab(idx).name);
end loop;
end;
/
То есть, ожидаю результат: emp_tab(20).name = Nicole.
PS версия в оригинальном вопросе - 11G.
Свободный перевод вопроса Oracle PL/SQL: search record type value от участника @Tomic
Ответы (2 шт):
Надо индексировать коллекцию по emp.id. Но для заполнения ее результатом запроса нельзя будет использовать bulk collect, по крайней мере не в 11g, это возможно будет добавлленно в версии 20c.
declare
type emptab is table of emp%rowtype index by pls_integer;
emps emptab;
id emp.id%type;
begin
for r in (select id, name, age from emp) loop
emps(r.id).name := r.name;
emps(r.id).age := r.age;
end loop;
dbms_output.put_line (emps(20).name||' age='||emps(20).age);
end;
/
Nicole age=30
Свободный перевод ответа от участника @William Robertson
Для инициализации ассоциативной коллекции с ключом, полученным как занчение одной из колонок, можно для более эффективного FETCH воспользоваться BULK COLLECT, а затем, одноразово индексировать коллекцию.
Воспроизводимый пример:
declare
type emparr is table of emp%rowtype index by pls_integer;
rc sys_refcursor;
emps emparr;
function initarr (rc sys_refcursor) return emparr is
res emparr;
ret emparr;
begin
fetch rc bulk collect into res;
close rc;
for i in 1..res.count loop
ret(res(i).id).id := res(i).id;
ret(res(i).id).name := res(i).name;
ret(res(i).id).age := res(i).age;
end loop;
return ret;
end;
begin
open rc for select * from emp;
emps := initarr (rc);
dbms_output.put_line ('name='||emps(20).name||' age='||emps(20).age);
end;
/
name=Nicole age=30