Коллекции
Коллекцией называется структура данных, по своей функциональности сходная со списком или одномерным массивом. В сущности, коллекция — ближайший аналог традиционных массивов в программах PL/SQL. Эта глава поможет вам решить, какой из трех разных типов коллекций (ассоциативный массив, вложенная таблица, VARRAY) лучше всего соответствует потребностям вашей программы. Также вы познакомитесь с примерами определения этих структур и работы с ними. Несколько типичных ситуаций для применения коллекций:
- Ведение списков данных в программах. Вероятно, это самое частое применение коллекций в программах. Да, с таким же успехом можно воспользоваться реляционными таблицами, глобальными временными таблицами (работа с которыми потребует частых переключений контекста) или строками с разделителями, но коллекции чрезвычайно эффективны, а код работы с ними получается очень выразительным и простым в сопровождении.
- Ускорение многострочных операций SQL на порядок и более. Использование коллекций в сочетании с конструкциями FORALL и BULK COLLECT радикально повышает производительность многострочных операций SQL.
- Кэширование информации базы данных. Коллекции хорошо подходят для кэширования статической информации, которая часто запрашивается в ходе одного сеанса (или просто многократно запрашивается в ходе выполнения одной программы) для повышения производительности поиска.
Концепции и терминология
Следующие пояснения помогут быстрее освоить эти структуры данных.
- Элементы и индексы. Коллекция состоит из множества элементов (фрагментов данных), причем каждый элемент находится в определенной позиции списка, то есть обладает определенным индексом. Иногда элементы называются «строками», а индексы — «номерами строк».
- Тип коллекции. Каждая переменная, представляющая коллекцию в программе, должна быть объявлена на основании заранее определенного типа коллекции. Как упоминалось ранее, коллекции делятся на три широкие категории: ассоциативные массивы, вложенные таблицы и VARRAY. В этих категориях существуют конкретные типы, которые определяются командой TYPE в разделе объявлений блока. Далее программист объявляет и использует экземпляры этих типов в своих программах.
- Коллекция, или экземпляр коллекции. Этот термин может иметь несколько значений:
- переменная PL/SQL типа ассоциативного массива, вложенной таблицы или VARRAY;
- столбец таблицы, где хранятся значения типа вложенной таблицы или массива VARRAY.
Отчасти из-за синтаксиса и названий, которые были выбраны для поддержки коллекций Oracle, коллекции также иногда называются массивами и таблицами.
- Однородные элементы. Все элементы коллекции должны относиться к одному типу, то есть коллекция является однородной. Впрочем, этот тип данных может быть составным; например, можно объявить коллекцию, состоящую из записей, то есть таблицу. Начиная с Oracle9i, поддерживается возможность объявления многоуровневых коллекций: полем коллекции служит коллекция или запись, полем которой, в свою очередь, также является коллекция или запись и т. д.
- Одномерная коллекция. В каждой строке коллекции имеется всего одно поле, и с этой точки зрения она похожа на одномерный массив. Нельзя объявить коллекцию, на элементы которой можно было бы ссылаться следующим образом:
my_collection (10, 44)
Двумерные структуры в настоящее время напрямую не поддерживаются, однако вы можете создать многомерный массив, объявляя коллекцию коллекцией, — синтаксис будет примерно таким:
my_collection (44) (10)
- Ограниченная и неограниченная коллекция. Коллекция называется ограниченной, если заранее определены границы возможных значений индексов (номеров) ее элементов. Если же верхняя или нижняя граница номеров элементов не указана, то коллекция называется неограниченной. Коллекции типа VARRAY (массивы переменной длины) всегда ограничены. При определении такой коллекции следует указать максимальное количество ее элементов (номер первого элемента всегда равен 1). Вложенные таблицы и ассоциативные массивы ограничиваются только теоретически. В тексте они будут описываться как неограниченные, потому что с теоретической точки зрения максимальное количество элементов в них может быть произвольным.
- Разреженные и плотные коллекции. Коллекция (или массив, или список) называется плотной, если все ее элементы, от первого до последнего, определены и каждому из них присвоено некоторое значение (таковым может быть и NULL). Коллекция считается разреженной, если отдельные ее элементы отсутствуют, как в рассмотренном выше примере. Не обязательно определять все элементы коллекции и заполнять ее полностью. Массивы VARRAY всегда являются плотными. Вложенные таблицы первоначально всегда плотные, но по мере удаления некоторых элементов становятся разреженными. Ассоциативные массивы могут быть как разреженными, так и плотными в зависимости от способа их заполнения.
Разреженность — это очень ценное свойство, позволяющее добавлять элементы в коллекцию по первичному ключу или другим ключевым данным (например, номерузаписи). Таким образом можно задать определенный порядок следования данных в коллекции или значительно ускорить их поиск.
- Целочисленное индексирование. К любому элементу коллекции можно обратиться по номеру, который представляет собой целочисленное значение. Объявление ассоциативного массива явно выражает это требование условием INDEX BY, но правило действует и для других типов коллекций.
- Строковое индексирование. Начиная с Oracle9i Release 2, в качестве индексов ассоциативных массивов можно использовать не только номера, но и символьные строки (в настоящее время до 32 Кбайт длиной). Эта возможность не поддерживается ни для вложенных таблиц, ни для массивов VARRAY.
- Внешняя таблица. Так называют таблицу, содержащую столбец типа вложенной таблицы или массива VARRAY.
- Внутренняя таблица. Так принято называть коллекцию, содержащуюся в столбце таблицы.
Разновидности коллекций
Как упоминалось ранее, Oracle поддерживает три разновидности коллекций. Несмотря на ряд общих характеристик, все эти разновидности обладают специфическими особенностями, которые будут охарактеризованы ниже.
- Ассоциативные массивы. Это одномерные неограниченные разреженные коллекции, состоящие из однородных элементов, доступные только в PL/SQL. Ранее в PL/SQL 2 (из поставки Oracle7) они назывались таблицами PL/SQL, а в Oracle8 и Oracle8i — индексируемыми таблицами (поскольку при объявлении такой коллекции приходилось явно указывать, что она «индексируется» номером строки). В Oracle9i Release 1 они были названы ассоциативными массивами. Этот термин выбран потому, что предложение INDEX BY может использоваться для индексирования содержимого коллекций посредством значений типа VARCHAR2 или PLS_INTEGER.
- Вложенные таблицы. Так называются одномерные несвязанные коллекции, также состоящие из однородных элементов. Первоначально они заполняются полностью, но позднее из-за удаления некоторых элементов могут стать разреженными. Вложенные таблицы могут определяться и в PL/SQL, и в базах данных (например,в качестве столбцов таблиц). Вложенные таблицы представляют собой мультимножества, то есть элементы вложенной таблицы не упорядочены.
- Массив типа VARRAY. Подобно двум другим типам коллекций, массивы VARRAY (массивы переменной длины) также являются одномерными коллекциями, состоящими из однородных элементов. Однако их размер всегда ограничен, и они не бывают разреженными. Как и вложенные таблицы, массивы VARRAY используются и в PL/SQL, и в базах данных. Однако порядок их элементов при сохранении и выборке, в отличие от вложенных таблиц, сохраняется.
Встроенные методы коллекций
- COUNT (функция) Возвращает текущее значение элементов в коллекции
- DELETE (процедура) Удаляет из коллекции один или несколько элементов. Уменьшает значение, возвращаемое функцией COUNT, если заданные элементы еще не удалены. Со структурами VARRAY может использоваться только для удаления всего содержимого
- EXISTS (функция) Возвращает значение TRUE или FALSE, определяющее, существует ли в коллекции заданный элемент
- EXTEND (процедура) Увеличивает количество элементов во вложенной таблице или VARRAY, а также значение, возвращаемое функцией COUNT
- FIRST, LAST (функции) Возвращают индексы первого (FIRST) и последнего (LAST) элемента в коллекции
- LIMIT (функция) Возвращает максимальное количество элементов в массиве VARRAY
- PRIOR, NEXT (функции) Возвращают индексы элементов, предшествующих заданному (PRIOR) и следующему за ним (NEXT). Всегда используйте PRIOR и NEXT* для перебора коллекций, особенно при работе с разреженными (или потенциально разреженными) коллекциями
- TRIM (функция) Удаляет элементы, начиная с конца коллекции (элемент с наибольшим индексом)
Объявление типов коллекций
Прежде чем работать с коллекцией, ее необходимо объявить, причем объявление должно базироваться на типе коллекции. Таким образом, прежде всего необходимо научиться определять типы коллекций. Существует два способа определения типов коллекций:
- Тип коллекции можно объявить в программе PL/SQL с применением синтаксиса TYPE. Такой тип будет доступен лишь в том блоке, где он был объявлен. Тип, определяемый в спецификации пакета, будет доступен всем программам, схема которых обладает правами EXECUTE для данного пакета.
- Определение типа вложенной таблицы или VARRAY как объекта уровня схемы в базе данных Oracle с использованием команды CREATE TYPE. В дальнейшем такой тип может использоваться в качестве типа столбцов таблиц баз данных и атрибутах объектных типов, а также для объявления переменных в программах PL/SQL. Он может использоваться в любой программе схемы, обладающей соответствующими правами EXECUTE.
Объявление ассоциативного массива
Конструкция TYPE для определения ассоциативного массива имеет следующий формат:
TYPE имя_типа_таблицы IS TABLE OF тип_данных [ NOT NULL ] INDEX BY тип_индекса;
Здесь имя_типа_таблицы — имя создаваемой коллекции, тип_данных — тип данных единственного столбца коллекции, а тип_индекса — тип данных индекса, используемого для упорядочения содержимого коллекции. При желании можно добавить ограничение NOT NULL, указывающее, что каждая строка таблицы обязательно должна содержать значение.
Несколько примеров объявлений типов ассоциативных массивов:
-- Список дат
TYPE birthdays_tt IS TABLE OF DATE INDEX BY PLS_INTEGER;
-- Список идентификаторов компаний
TYPE company_keys_tt IS TABLE OF company.company_id%TYPE NOT NULL INDEX BY PLS_INTEGER;
-- Список записей книг; эта структура позволяет создать "локальную" копию таблицы книг в программе PL/SQL.
TYPE booklist_tt IS TABLE OF books%ROWTYPE INDEX BY NATURAL;
Объявление вложенной таблицы или VARRAY
Как и в случае с ассоциативными массивами, перед объявлением вложенной таблицы или VARRAY также необходимо определить тип. Эти типы определяются либо в базе данных, либо в блоке PL/SQL. Тип данных вложенной таблицы, которая существует в базе данных (а не только в коде PL/SQL), создается следующим образом:
CREATE [ OR REPLACE ] TYPE имя_типа AS | IS TABLE OF тип_элемента [ NOT NULL ];
Тип данных VARRAY, который существует в базе данных (а не только в коде PL/SQL), создается следующим образом:
CREATE [ OR REPLACE ] TYPE имя_типа AS | IS VARRAY (максимальный_индекс) OF тип_элемента [ NOT NULL ];
Удаление типа осуществляется следующей командой:
DROP TYPE имя_типа [ FORCE ];
А вот как в программе PL/SQL создается тип вложенной таблицы:
TYPE имя_типа IS TABLE OF тип_элемента [ NOT NULL ];
Для объявления типа данных VARRAY в PL/SQL используется объявление:
TYPE имя_типа IS VARRAY (максимальный_индекс) OF тип_элемента [ NOT NULL ];
Вопросы для самопроверки
- Что такое коллекция?
- Какие коллекции называются разреженными и плотными?
- Какие коллекции называются ограниченными и неограниченными
- Перечислите встроенные методы коллекций
- Какие типы коллекций существуют?
Задания
- Объявите ассоциативный массив
- Объявите вложенную таблицу
- Объявите коллекцию varray