›  ›  ›  › Разновидности коллекций в PL/SQL Oracle

Разновидности коллекций в PL/SQL Oracle

Oracle поддерживает три разновидности коллекций. Несмотря на ряд общих характеристик, все эти разновидности обладают специфическими особенностями.

  • Ассоциативные массивы. Это одномерные неограниченные разреженные коллекции, состоящие из однородных элементов, доступные только в PL/SQL. Этот термин выбран потому, что предложение INDEX BY может использоваться для индексирования содержимого коллекций посредством значений типа VARCHAR2 или PLS_INTEGER.
  • Вложенные таблицы. Так называются одномерные несвязанные коллекции, также состоящие из однородных элементов. Первоначально они заполняются полностью, но позднее из-за удаления некоторых элементов могут стать разреженными. Вложенные таблицы могут определяться и в PL/SQL, и в базах данных (например, в качестве столбцов таблиц). Вложенные таблицы представляют собой мультимножества, то есть элементы вложенной таблицы не упорядочены.
  • Массив типа VARRAY. Подобно двум другим типам коллекций, массивы VARRAY (массивы переменной длины) также являются одномерными коллекциями, состоящими из однородных элементов. Однако их размер всегда ограничен, и они не бывают разреженными. Как и вложенные таблицы, массивы VARRAY используются и в PL/SQL, и в базах данных. Однако порядок их элементов при сохранении и выборке, в отличие от вложенных таблиц, сохраняется.

Примеры коллекций

Сейчас будут рассмотренные относительно простые примеры всех разновидностей коллекций с описанием их основных характеристик.

Ассоциативный массив

В этом примере объявляется тип ассоциативного массива, а затем коллекция, основанная на этом типе. Коллекция заполняется четырьмя элементами, после чего выполняется перебор её содержимого и вывод символьных строк. Подробно разъяснение приведено после примера.

DECLARE
   TYPE list_of_names_t IS TABLE OF person.first_name%TYPE
      INDEX BY PLS_INTEGER;
   happyfamily   list_of_names_t;
   l_row PLS_INTEGER;
BEGIN
   happyfamily (2020202020) := 'Eli';
   happyfamily (-15070) := 'Steven';
   happyfamily (-90900) := 'Chris';
   happyfamily (88) := 'Veva';

   l_row := happyfamily.FIRST;

    WHILE (l_row IS NOT NULL)
    LOOP
      DBMS_OUTPUT.put_line (happyfamily (l_row));
      l_row := happyfamily.NEXT (l_row);
   END LOOP;
END;

/*
Результат:
Chris
Steven
Veva
Eli
*/
Строки Описание
2-3 Объявление ассоциативного массива TYPE с характерной секцией INDEX BY. Коллекция, созданная на основе этого типа, содержит список строк, каждая из которых может достигать по длине столбца first_name таблицы person
4 Объявление коллекции happyfamily на базе типа list_of_names_t
9-10 Заполнение коллекции четырьмя именами. Обратите внимание: можно использовать любые целочисленные значения по своему усмотрению. Номера строк в ассоциативном массиве не обязаны быть последовательными; они даже могут быть отрицательными!
12 Вызов метода FIRST (функция, «прикрепленная» к коллекции) для получения первого (минимального) номера строки в коллекции
14-18 Перебор содержимого коллекции в цикле WHILE, с выводом каждой строки. В строке 17 вызывается метод NEXT, который переходит от текущего элемента к следующему без учета промежуточных пропусков

Вложенная таблица

Следующий пример начинается с объявления типа вложенной таблицы как типа уровня схемы. На основании этого типа в блоке PL/SQL объявляются три вложенные таблицы. Имена членов семьи сохраняются во вложенной таблице happyfamily, имена детей — во вложенной таблице children, после чего команда MULTISET EXCEPT используется для извлечения из вложенной таблицы happyfamily только имен родителей. Подробное разъяснение приводится после примера.

REM Раздел A

CREATE TYPE list_of_names_t IS TABLE OF VARCHAR2 (100);
Type created.

REM Раздел B

DECLARE
   happyfamily   list_of_names_t := list_of_names_t ();
   children      list_of_names_t := list_of_names_t ();
   parents       list_of_names_t := list_of_names_t ();
BEGIN
   happyfamily.EXTEND (4);
   happyfamily (1) := 'Eli';
   happyfamily (2) := 'Steven';
   happyfamily (3) := 'Chris';
   happyfamily (4) := 'Veva';

   children.EXTEND;
   children (1) := 'Chris';
   children.EXTEND;
   children (2) := 'Eli';

   parents := happyfamily MULTISET EXCEPT children;

   FOR l_row IN parents.FIRST .. parents.LAST
   LOOP
      DBMS_OUTPUT.put_line (parents (l_row));
   END LOOP;
END;

/*
Результат:
Steven
Veva
*/
Строки Описание
Раздел А Команда CREATE TYPE создает тип вложенной таблицы в самой базе данных. Такое решение позволяет объявлять вложенные таблицы в любой схеме, обладающей разрешениями EXECUTE для этого типа.
2-4 Объявление трех разных вложенных таблиц, созданных на основе типа уровня схемы. Обратите внимание: в каждом случае для инициализации вложенной таблицы вызывается функция-конструктор. Имя этой функции всегда совпадает с именем типа, а ее код автоматически генерируется Oracle. Вложенную таблицу необходимо инициализировать перед использованием
6 Вызов метода EXTEND «выделяет место» во вложенной таблице для данных членов семьи. В отличие от ассоциативных массивов, во вложенных таблицах необходимо явно выполнить операцию создания элемента, прежде чем размещать в нем данные
7-10 Заполнение коллекции happyfamily именами членов семьи
12-15 Заполнение коллекции children. В данном случае данные добавляются в коллекцию по строкам
17 Чтобы получить информацию о родителях, достаточно убрать из happyfamily данные children. Эта задача особенно легко решается, с появлением высокоуровневых команд для работы с множествами вроде MULTISET EXCEPT (близкий аналог коллекции SQL MINUS). Обратите внимание: перед заполнением parents вызывать метод EXTEND не нужно. База данных делает это автоматически
19-22 Поскольку операция MULTISET EXCEPT плотно заполняет коллекцию parents, для перебора содержимого коллекции можно воспользоваться циклом FOR со счетчиком. При использовании этой конструкции с разреженной коллекцией произойдет исключение NO_DATA_FOUND

VARRAY

Данный пример демонстрирует использование типов VARRAY в качестве столбцов реляционной таблицы. Сначала мы объявляем два разных типа VARRAY уровня схемы, после чего создаем реляционную таблицу family с двумя столбцами VARRAY. Наконец, в коде PL/SQL заполняются две локальные коллекции, используемые при выполнении операции INSERT с таблицей family. Подробное разъяснение приводится после примера.

REM Раздел A

CREATE TYPE first_names_t IS VARRAY (2) OF VARCHAR2 (100);
Type created.

CREATE TYPE child_names_t IS VARRAY (1) OF VARCHAR2 (100);
Type created.

REM Раздел B

CREATE TABLE family (
     surname VARCHAR2(1000)
   , parent_names first_names_t
   , children_names child_names_t
);

Table created.

REM Раздел C

DECLARE
   parents    first_names_t := first_names_t ();
   children   child_names_t := child_names_t ();
BEGIN
   parents.EXTEND (2);
   parents (1) := 'Samuel';
   parents (2) := 'Charina';
   --
   children.EXTEND;
   children (1) := 'Feather';

   --
   INSERT INTO family
               ( surname, parent_names, children_names )
        VALUES ( 'Assurty', parents, children );
END;

PL/SQL procedure successfully completed.
SQL> SELECT * FROM family;

/*
SURNAME
PARENT_NAMES
CHILDREN_NAMES
--------------------------------------------
Assurty
FIRST_NAMES_T('Samuel', 'Charina')
CHILD_NAMES_T('Feather')
*/
Строки Описание
Раздел А Команда CREATE TYPE используется для создания двух типов VARRAY. Обратите внимание: с типом VARRAY необходимо задать максимальную длину коллекции. По сути объявления определяют некое подобие «социальной политики»: не более двух родителей и не более одного ребенка
Раздел B Создание реляционной таблицы из трех столбцов: VARCHAR2 для фамилии и двух столбцов VARRAY (для родителей и детей)
Раздел C, строки 2–3 Объявление двух локальных экземпляров VARRAY на основании типа уровня схемы. По аналогии с вложенными таблицами (и в отличие от ассоциативных массивов), мы должны вызвать функцию-конструктор, имя которой совпадает с именем TYPE, для инициализации структур
5-10 Расширение и заполнение коллекций; добавляются имена родителей и одного ребенка. При попытке добавления второго ребенка произойдет ошибка
13-15 Чтобы вставить строку в таблицу family, достаточно включить VARRAY в список значений.

Метки: , .

Записи по теме

Добавить комментарий

Ваш адрес email не будет опубликован.