Oracle PL / SQL - Как создать простую переменную массива?

88

Я хотел бы создать переменную массива в памяти, которая может использоваться в моем коде PL/SQL. Я не могу найти какие-либо коллекции в Oracle PL/SQL, которые используют чистую память, все они, похоже, связаны с таблицами. Я хочу сделать что-то подобное в моем синтаксисе PL/SQL (С#):

string[] arrayvalues = new string[3] {"Matt", "Joanne", "Robert"};

Edit: Oracle: 9i

  • 2
    Смотрите: PL / SQL Коллекции и записи
  • 1
    Ссылка «таблица», как правило, представляет собой похмелье от именования старых таблиц PL / SQL. VARRAY, ассоциативные массивы и объявленные вложенные таблицы - все это типы массивов в памяти.
Показать ещё 1 комментарий
Теги:
plsql
oracle9i

4 ответа

172
Лучший ответ

Вы можете использовать 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;

Или TABLE для неограниченного массива:

...
   type array_t is table of varchar2(10);
...

Слово "таблица" здесь не имеет ничего общего с таблицами базы данных, смутно. Оба метода создают массивы в памяти.

С любым из них вам нужно как инициализировать, так и расширять коллекцию перед добавлением элементов:

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;

Первый индекс равен 1 не 0.

  • 52
    «сбивает с толку» просто подводит итог Oracle
  • 0
    Вставлять в таблицы так же, как массивы? т.е. my_array(0) := 'some string';
Показать ещё 6 комментариев
48

Вы можете просто объявить 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;

Вы можете использовать ассоциативный массив (обычно называемый 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;

Ассоциативный массив может содержать любые типы записей.

Надеюсь, что это поможет, Олли.

  • 4
    Это в дополнение к ответу Тони выше, который является хорошим ответом ...
  • 15
    Условие итерации вызывает VALUE_ERROR когда коллекция пуста. Я бы предложил использовать FOR i IN 1 .. employee_array.COUNT в этом случае
Показать ещё 1 комментарий
6

Другим решением является использование коллекции Oracle в виде 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 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 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;
4

Вы также можете использовать 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;

Я бы использовал массив in-memory. Но с улучшением .COUNT, предложенным uziberia:

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;

Другим решением было бы использовать Hashmap, например @Jchomel здесь

Примечание:

С Oracle 12c вы можете даже массивы запросов прямо сейчас!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню