如何在PLSQL中填充内存表?

时间:2012-08-29 21:46:52

标签: oracle collections plsql

我不知道它是否是正确的术语,但我将“在内存表中”称为这样创建的对象:

create type InMemReg is object (field1 varchar2(10), field2 varchar2(20), field3 number);
create type InMemTab is table of InMemReg;

在这种情况下,我的“内存表”是“InMemTab”。我的问题是,当我以前不知道元素的数量时,我如何填充这种对象?我在某些地方看到过这种类型的初始化:

declare
  v_uno InMemReg := InMemReg('a','b',1999);
  v_dos InMemReg := InMemReg('A','Z',2000);
  t_tres  InMemTab := InMemTab();
begin
  t_tres := InMemTab(v_uno, v_dos);

在这种情况下,我在初始化“t_tres”之前有明确的2个对象,但在动态场景中,我可能有n个元素,我不知道如何填充它。

在另一种OO语言中可能是这样的:

t_tres.add(OtherObject)

2 个答案:

答案 0 :(得分:10)

类型InMemTab是Oracle用语中的嵌套表。

等同于add方法的方法是调用extend方法,然后将OtherObject分配给嵌套表中的最后一个位置。

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    v_uno InMemReg := InMemReg('a','b',1999);
  3    v_dos InMemReg := InMemReg('A','Z',2000);
  4    t_tres  InMemTab := InMemTab();
  5  begin
  6    t_tres.extend;
  7    t_tres( t_tres.count ) := v_uno;
  8    t_tres.extend;
  9    t_tres( t_tres.count ) := v_dos;
 10    dbms_output.put_line( 't_tres has ' || t_tres.count || ' elements.' );
 11* end;
 12  /
t_tres has 2 elements.

PL/SQL procedure successfully completed.

您可以将其分解为add程序

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    v_uno InMemReg := InMemReg('a','b',1999);
  3    v_dos InMemReg := InMemReg('A','Z',2000);
  4    t_tres  InMemTab := InMemTab();
  5    procedure add( p_nt    IN OUT InMemTab,
  6                   p_elem  IN     InMemReg )
  7    as
  8    begin
  9      p_nt.extend;
 10      p_nt( p_nt.count ) := p_elem;
 11    end;
 12  begin
 13    add( t_tres, v_uno );
 14    add( t_tres, v_dos );
 15    dbms_output.put_line( 't_tres has ' || t_tres.count || ' elements.' );
 16* end;
 17  /
t_tres has 2 elements.

PL/SQL procedure successfully completed.

答案 1 :(得分:7)

通常从数据本身填充集合,这意味着您没有显式添加字符串和数字集,而是从其他表中提取数据。因为这是与集合相关的常见和自然的事情,所以Oracle通过pl / sql中的“BULK COLLECT INTO”子句轻松实现。例如:

DECLARE
   TYPE EmployeeSet IS TABLE OF employees%ROWTYPE;
   underpaid EmployeeSet;
     -- Holds set of rows from EMPLOYEES table.
   CURSOR c1 IS SELECT first_name, last_name FROM employees;
   TYPE NameSet IS TABLE OF c1%ROWTYPE;
   some_names NameSet;
     -- Holds set of partial rows from EMPLOYEES table.
BEGIN
-- With one query,
-- bring all relevant data into collection of records.
   SELECT * BULK COLLECT INTO underpaid FROM employees
      WHERE salary < 5000 ORDER BY salary DESC;
-- Process data by examining collection or passing it to
-- eparate procedure, instead of writing loop to FETCH each row.
   DBMS_OUTPUT.PUT_LINE
     (underpaid.COUNT || ' people make less than 5000.');
   FOR i IN underpaid.FIRST .. underpaid.LAST
   LOOP
     DBMS_OUTPUT.PUT_LINE
       (underpaid(i).last_name || ' makes ' || underpaid(i).salary);
   END LOOP;
-- You can also bring in just some of the table columns.
-- Here you get the first and last names of 10 arbitrary employees.
   SELECT first_name, last_name
     BULK COLLECT INTO some_names
     FROM employees
     WHERE ROWNUM < 11;
   FOR i IN some_names.FIRST .. some_names.LAST
   LOOP
      DBMS_OUTPUT.PUT_LINE
        ('Employee = ' || some_names(i).first_name
         || ' ' || some_names(i).last_name);
   END LOOP;
END;
/

您通常不需要担心扩展或您将拥有多少元素,您通常可以将其插入,然后根据需要使用集合的内置功能(计数,循环,比较不同的集合) ,设置操作等)