PL / SQL批量收集到具有稀疏键的关联数组

时间:2010-04-26 18:08:33

标签: oracle plsql associative-array

我想在PL / SQL中执行SQL查询,并将结果填充到关联数组中,其中SQL中的一列成为关联数组中的键。例如,假设我有一个带有列

的表Person
PERSON_ID   INTEGER      PRIMARY KEY
PERSON_NAME VARCHAR2(50)

......和价值观如下:

 PERSON_ID  |  PERSON_NAME
 ------------------------
 6          |  Alice
 15         |  Bob
 1234       |  Carol

我想将此表格批量收集到TABLE OF VARCHAR2(50) INDEX BY INTEGER,以使此关联数组中的键6具有值Alice,依此类推。可以在PL / SQL中完成吗?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:14)

不,您必须使用2个集合(id,name)或其元素类型为记录的集合。

以下是后者的样本:

  cursor getPersonsCursor is
    SELECT ID, Name
    FROM   Persons
    WHERE  ...;

  subtype TPerson is getPersonsCursor%rowtype;
  type TPersonList is table of TPerson;
  persons TPersonList;
begin

open getPersonsCursor;
fetch getPersonsCursor
  bulk collect into persons;
close getPersonsCursor;

if persons.Count > 0 then
  for i in persons.First .. persons.Last loop
    yourAssocArray(persons(i).ID) := persons(i).Name;
  end loop;
end if;

答案 1 :(得分:6)

如果我们想在关联数组的索引中指定值,那么我们必须使用以下语法:

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5  begin
  6      for r in ( select ename, empno from emp )
  7      loop
  8          emp_names(r.empno) := r.ename;
  9      end loop;
 10
 11      dbms_output.put_line('count='||emp_names.count()
 12                               ||'::last='||emp_names.last());
 13      dbms_output.put_line(emp_names(8085));
 14
 15  end;
 16  /
count=19::last=8085
TRICHLER

PL/SQL procedure successfully completed.

SQL>

我们可以使用批量收集填充关联数组,但仅当索引是整数时,我们很乐意通过(隐式)ROWNUM索引,即不是稀疏键...

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5  begin
  6      select ename
  7      bulk collect into emp_names
  8      from emp ;
  9
 10      dbms_output.put_line('count='||emp_names.count()
 11                               ||'::last='||emp_names.last());
 12      dbms_output.put_line(emp_names(19));
 13
 14  end;
 15  /
count=19::last=19
FEUERSTEIN

PL/SQL procedure successfully completed.

SQL>

公平地说,如果你需要使用BULK COLLECT,你可能正在处理的数据多于适用于关联数组的数据。

修改

这两种方法的低成本性能测试:

SQL> declare
  2      type n_array is table of varchar2(30)
  3           index by binary_integer;
  4      emp_names n_array;
  5      s_time pls_integer;
  6      e_time pls_integer;
  7  begin
  8      s_time := dbms_utility.get_time;
  9      select ename
 10      bulk collect into emp_names
 11      from big_emp
 12      where rownum <= 500;
 13      dbms_output.put_line('bulk collect elapsed time = '
 14                              ||to_char(dbms_utility.get_time - s_time));
 15      s_time := dbms_utility.get_time;
 16      for r in ( select ename, empno from big_emp
 17                 where rownum <= 500 )
 18      loop
 19          emp_names(r.empno) := r.ename;
 20      end loop;
 21      dbms_output.put_line('sparse array elapsed time = '
 22                              ||to_char(dbms_utility.get_time - s_time));
 23  end;
 24  /

bulk collect elapsed time = 0
sparse array elapsed time = 0

PL/SQL procedure successfully completed.

SQL>

华尔街的性能测试非常出色。但是对于几百条记录,任何差异都不值得担心,当然在我们可能想要使用相关阵列的地方。

修改2

@Dan说:

  在我看来,想要查询一个   大小合适的行数   可用于的数据结构   恒定时间查找应该是一个   很常见的需求

这实际上取决于你对“一个体面的数字”的定义。是否真的有很多情况需要使用字符串索引填充带有数千行的关联数组?当我们得到这些数字时,普通的数据库表可能同样有用,特别是在11g Enterprise Edition with resultset caching上。