Коллекции и записи
Составной тип данных хранит значения, которые имеют внутренние компоненты. Вы можете передать целые составные переменные подпрограммам в качестве параметров, а также получить доступ к внутренним компонентам составных переменных по отдельности. Внутренние компоненты могут быть скалярными или составными. Вы можете использовать скалярные компоненты везде, где вы можете использовать скалярные переменные. PL/SQL позволяет вам определять два вида составных типов данных: коллекция и запись. Вы можете использовать составные компоненты везде, где вы можете использовать составные переменные одного типа.
Записи |
|
Record | Запись |
%ROWTYPE | Модификатор записи |
%TYPE | Модификатор столбца |
Коллекции |
|
Associative Arrays | Ассоциативные массивы |
Varrays | Массивы переменной длины |
Nested Tables | Вложенные таблицы |
Методы коллекций
Метод коллекции - это подпрограмма PL/SQL - либо функция, которая возвращает информацию о коллекции, либо процедура, которая работает с коллекцией. Методы сбора данных упрощают использование коллекций и упрощают поддержку ваших приложений.
С нулевой коллекцией EXISTS является единственным методом сбора, который не вызывает предопределенное исключение COLLECTION_IS_NULL.
Метод коллекции | Тип | Описание |
---|---|---|
DELETE | Процедура | Удаляет элементы из коллекции. |
TRIM | Процедура | Удаляет элементы из конца varray или Nested Tables. |
EXTEND | Процедура | Добавляет элементы в конец varray или Nested Tables. |
EXISTS | Функция | Возвращает TRUE тогда и только тогда, когда существует определенный элемент varray или Nested Tables. |
FIRST и LAST | Функции | FIRST возвращает первый, LAST последний индекс в коллекции. |
COUNT | Функция | Возвращает количество элементов в коллекции. |
LIMIT | Функция | Возвращает максимальное количество элементов, которые может иметь коллекция. |
PRIOR и NEXT | Функции | PRIOR возвращает индекс, который предшествует указанному индексу, NEXT возвращает индекс, который следует за указанным индексом. |
Операции над коллекциями
MULTISET UNION | Возвращает объединение двух коллекций |
MULTISET UNION DISTINCT | Возвращает объединение двух коллекций с дистинктом (убирает дубли) |
MULTISET INTERSECT | Возвращает пересечение двух коллекций |
MULTISET INTERSECT DISTINCT | Возвращает пересечение двух коллекций с дистинктом (убирает дубли) |
SET | Возвращает коллекцию с дистинктом (т.е. коллекцию без дублей) |
MULTISET EXCEPT | Возвращает разницу (усечение) двух коллекций |
MULTISET EXCEPT DISTINCT | Возвращает разницу (усечение) двух коллекций с дистинктом (убирает дубли) |
Исключительные ситуации коллекции.
В большинстве случаев, если вы ссылаетесь на несуществующий элемент коллекции, PL/SQL вызывает предопределенное исключение. Рассмотрим следующий пример:
1 2 3 4 5 6 7 8 9 10 11 12 |
DECLARE TYPE NumList IS TABLE OF NUMBER; nums NumList; -- атомарно null BEGIN /*Предположим, что выполнение продолжается, несмотря на возникшие исключения.*/ nums(1) := 1; -- возникает COLLECTION_IS_NULL (1) nums := NumList(1,2); -- инициализация таблицы nums(NULL) := 3 -- возникает VALUE_ERROR (2) nums(0) := 3; -- возникает SUBSCRIPT_OUTSIDE_LIMIT (3) nums(3) := 3; -- возникает SUBSCRIPT_BEYOND_COUNT (4) nums.DELETE(1); -- удаляет элемент 1 IF nums(1) = 1 THEN ... -- возникает NO_DATA_FOUND (5) |
- В первом случае вложенная таблица атомарно равна NULL.
- Во втором случае индекс равен NULL.
- В третьем случае индекс находится за пределами допустимого диапазона.
- В четвертом случае индекс превышает количество элементов в таблице.
- В пятом случае индекс обозначает удаленный элемент.
Следующий список показывает, когда возникает данное исключение:
Исключение коллекции | Когда возникает |
---|---|
COLLECTION_IS_NULL | вы пытаетесь оперировать с атомарно нулевой коллекцией. |
NO_DATA_FOUND | обозначает элемент, который был удален, или несуществующий элемент ассоциативного массива. |
SUBSCRIPT_BEYOND_COUNT | индекс превышает количество элементов в коллекции. |
SUBSCRIPT_OUTSIDE_LIMIT | индекс находится за пределами допустимого диапазона. |
VALUE_ERROR | индекс не имеет значения или не может быть преобразован в тип ключа. Это исключение может возникнуть, если ключ определен как диапазон PLS_INTEGER, а индекс находится за пределами этого диапазона. |
В некоторых случаях вы можете передавать недопустимые индексы в метод, не вызывая исключения. Например, когда вы передаете нулевой индекс процедуре DELETE, она ничего не делает. Кроме того, вы можете заменить удаленные элементы, без возникновения NO_DATA_FOUND, как показано в следующем примере:
1 2 3 4 5 6 7 8 9 10 |
DECLARE TYPE NumList IS TABLE OF NUMBER; nums NumList := NumList(10,20,30); -- инициализация таблицы BEGIN nums.DELETE(-1); -- не возникает SUBSCRIPT_OUTSIDE_LIMIT nums.DELETE(3); -- удалит 3-й элемент dbms_output.put_line(nums.COUNT); -- печатает 2 nums(3) := 30; -- допустимо; не возникает NO_DATA_FOUND dbms_output.put_line(nums.COUNT); -- печатает 3 END; |
Типы коллекций пакетов и локальные типы коллекций никогда не совместимы. Например, предположим, что вы хотите вызвать следующую процедуру пакета:
1 2 3 4 5 6 7 8 9 |
CREATE PACKAGE pkg1 AS TYPE NumList IS VARRAY(25) OF NUMBER(4); PROCEDURE delete_emps (emp_list NumList); END pkg1; CREATE PACKAGE BODY pkg1 AS PROCEDURE delete_emps (emp_list NumList) IS ... ... END pkg1; |
Когда вы запускаете нижеприведенный блок PL/SQL, второй вызов процедуры завершается неудачно с ошибочным номером или типом аргументов. Это связано с тем, что пакетные и локальные типы VARRAY несовместимы, даже если их определения идентичны.
1 2 3 4 5 6 7 8 |
DECLARE TYPE NumList IS VARRAY(25) OF NUMBER(4); emps pkg1.NumList := pkg1.NumList(7369, 7499); emps2 NumList := NumList(7521, 7566); BEGIN pkg1.delete_emps(emps); pkg1.delete_emps(emps2); -- вызывает ошибку компиляции END; |