Oracle PL/SQL - 如何创建一个简单的数组变量?

con*_*att 124 oracle plsql oracle9i

我想创建一个可以在我的PL/SQL代码中使用的内存数组变量.我在Oracle PL/SQL中找不到任何使用纯内存的集合,它们似乎都与表相关联.我想在我的PL/SQL(C#语法)中做类似的事情:

string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"};
Run Code Online (Sandbox Code Playgroud)

编辑: Oracle:9i

Ton*_*ews 232

您可以将VARRAY用于固定大小的数组:

declare
   type array_t is varray(3) of varchar2(10);
   array array_t := array_t('Matt', 'Joanne', 'Robert');
begin
   for i in 1..array.count loop
       dbms_output.put_line(array(i));
   end loop;
end;
Run Code Online (Sandbox Code Playgroud)

或者表为无界数组:

...
   type array_t is table of varchar2(10);
...
Run Code Online (Sandbox Code Playgroud)

这里的"表"一词与数据库表无关,令人困惑.这两种方法都创建了内存数组.

使用其中任何一个,您需要在添加元素之前初始化和扩展集合:

declare
   type array_t is varray(3) of varchar2(10);
   array array_t := array_t(); -- Initialise it
begin
   for i in 1..3 loop
      array.extend(); -- Extend it
      array(i) := 'x';
   end loop;
end;
Run Code Online (Sandbox Code Playgroud)

第一个索引是1而不是0.

  • "令人困惑"只是总结了Oracle (65认同)
  • @Abdul,不,不.我从来没有使用可变数组正常,但测试上面的代码我检查时,如果你试图扩展`VARRAY(3)`4倍时会发生什么 - 你会得到一个"标超限"错误. (2认同)
  • 希望我多次投票这个答案@TonyAndrews,因为你覆盖了`array.extend()`.我看到的每个地方都没有显示这一点,并且它是能够添加多个项目的最重要的部分(从我对它的理解,对SQL中的数组仍然是新的). (2认同)

Oll*_*lie 58

您可以声明DBMS_SQL.VARCHAR2_TABLE来保存由BINARY_INTEGER索引的内存中可变长度数组:

DECLARE
   name_array dbms_sql.varchar2_table;
BEGIN
   name_array(1) := 'Tim';
   name_array(2) := 'Daisy';
   name_array(3) := 'Mike';
   name_array(4) := 'Marsha';
   --
   FOR i IN name_array.FIRST .. name_array.LAST
   LOOP
      -- Do something
   END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

您可以使用关联数组(以前称为PL/SQL表),因为它们是内存数组.

DECLARE
   TYPE employee_arraytype IS TABLE OF employee%ROWTYPE
        INDEX BY PLS_INTEGER;
   employee_array employee_arraytype;
BEGIN
   SELECT *
     BULK COLLECT INTO employee_array
     FROM employee
    WHERE department = 10;
   --
   FOR i IN employee_array.FIRST .. employee_array.LAST
   LOOP
      -- Do something
   END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

关联数组可以保存任何记录类型.

希望它有所帮助,奥利.

  • 当集合为空时,迭代条件会引发"VALUE_ERROR".我建议在这种情况下使用`FOR i IN 1 .. employee_array.COUNT` (16认同)

Jik*_*ika 11

你也可以使用 oracle defined collection

DECLARE 
  arrayvalues sys.odcivarchar2list;
BEGIN
  arrayvalues := sys.odcivarchar2list('Matt','Joanne','Robert');
  FOR x IN ( SELECT m.column_value m_value
               FROM table(arrayvalues) m )
  LOOP
    dbms_output.put_line (x.m_value||' is a good pal');
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

我会使用内存中的数组.但随着.COUNT乌兹别克的改善:

DECLARE
  TYPE t_people IS TABLE OF varchar2(10) INDEX BY PLS_INTEGER;
  arrayvalues t_people;
BEGIN
  SELECT *
   BULK COLLECT INTO arrayvalues
   FROM (select 'Matt' m_value from dual union all
         select 'Joanne'       from dual union all
         select 'Robert'       from dual
    )
  ;
  --
  FOR i IN 1 .. arrayvalues.COUNT
  LOOP
    dbms_output.put_line(arrayvalues(i)||' is my friend');
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是使用一个HashMap像@Jchomel没有在这里.

注意:

使用Oracle 12c,您甚至可以直接查询数组!


J. *_*mel 11

另一种解决方案是将Oracle Collection用作Hashmap:

declare 
-- create a type for your "Array" - it can be of any kind, record might be useful
  type hash_map is table of varchar2(1000) index by varchar2(30);
  my_hmap hash_map ;
-- i will be your iterator: it must be of the index's type
  i varchar2(30);
begin
  my_hmap('a') := 'apple';
  my_hmap('b') := 'box';
  my_hmap('c') := 'crow';
-- then how you use it:

  dbms_output.put_line (my_hmap('c')) ;

-- or to loop on every element - it's a "collection"
  i := my_hmap.FIRST;

  while (i is not null)  loop     
    dbms_output.put_line(my_hmap(i));      
    i := my_hmap.NEXT(i);
  end loop;

end;
Run Code Online (Sandbox Code Playgroud)