3

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

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)
4

2 回答 2

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.
于 2012-08-29T21:54:36.673 回答
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;
/

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

于 2012-08-31T01:12:08.493 回答