Oracle Коллекции PL/SQL: массивы Varrays, вложенность и индексирование по таблицам

Что такое коллекция?

Коллекция — это упорядоченная группа элементов определенных типов данных. Это может быть коллекция простых или сложных типов данных (например, определяемых пользователем типов или типов записей).

В коллекции каждый элемент идентифицируется термином, называемым «индекс». Каждому элементу коллекции присвоен уникальный индекс. Данными в этой коллекции можно манипулировать или извлекать их, обращаясь к этому уникальному индексу.

Коллекции наиболее полезны, когда необходимо обрабатывать или манипулировать большими данными одного типа. Коллекции можно заполнять и манипулировать ими целиком, используя опцию «BULK» в Oracle.

Коллекции классифицируются на основе структуры, индекса и хранилища, как показано ниже.

  • Индекс по таблицам (также известный как ассоциативный массив)
  • Вложенные таблицы
  • Варрайс

В любой момент данные в коллекции могут обозначаться тремя терминами: Имя коллекции, Индекс, Имя поля/столбца: « ( ). ». Подробнее об этих вышеупомянутых категориях коллекций вы узнаете далее в разделе ниже.

Варрайс

Varray — это метод сбора данных, в котором размер массива фиксирован. Размер массива не может превышать его фиксированное значение. Индекс Varray имеет числовое значение. Ниже приведены атрибуты Varrays.

  • Размер верхнего предела фиксирован
  • Заполняется последовательно, начиная с индекса «1».
  • Этот тип коллекции всегда плотный, т. е. мы не можем удалить элементы массива. Varray можно удалить целиком, а можно обрезать с конца.
  • Поскольку он всегда плотный по своей природе, он имеет очень меньшую гибкость.
  • Более целесообразно использовать, когда известен размер массива, и выполнять аналогичные действия со всеми элементами массива.
  • Индекс и последовательность всегда остаются стабильными, т. е. индекс и количество коллекции всегда одинаковы.
  • Их необходимо инициализировать перед использованием в программах. Любая операция (кроме операции EXISTS) с неинициализированной коллекцией приведет к ошибке.
  • Его можно создать как объект базы данных, видимый во всей базе данных или внутри подпрограммы, который можно использовать только в этой подпрограмме.

На рисунке ниже схематически показано распределение памяти Varray (плотного).

индекс 1 2 3 4 5 6 7
Значение Xyz Дфв Сде Cxs ВВС Nhu Qwe

Синтаксис VARRAY:

TYPE <type_name> IS VARRAY (<SIZE>) OF <DATA_TYPE>;
  • В приведенном выше синтаксисе имя_типа объявляется как VARRAY типа «DATA_TYPE» для заданного ограничения размера. Тип данных может быть простым или сложным.

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

Вложенная таблица — это коллекция, в которой размер массива не фиксирован. Он имеет числовой тип индекса. Ниже приведены дополнительные описания типов вложенных таблиц.

  • Вложенная таблица не имеет верхнего предела размера.
  • Поскольку верхний предел размера не фиксирован, память коллекции необходимо расширять каждый раз, прежде чем мы ее будем использовать. Мы можем расширить коллекцию, используя ключевое слово EXTEND.
  • Заполняется последовательно, начиная с индекса «1».
  • Этот тип коллекции может быть как плотный и редкий, то есть мы можем создать коллекцию как плотную, а также можем удалить отдельный элемент массива случайным образом, что сделает ее разреженной.
  • Это дает больше гибкости при удалении элемента массива.
  • Он хранится в созданной системой таблице базы данных и может использоваться в запросе выбора для получения значений.
  • Индекс и последовательность нестабильны, т.е. индекс и количество элементов массива могут меняться.
  • Их необходимо инициализировать перед использованием в программах. Любая операция (кроме операции EXISTS) с неинициализированной коллекцией приведет к ошибке.
  • Его можно создать как объект базы данных, видимый во всей базе данных или внутри подпрограммы, который можно использовать только в этой подпрограмме.

На рисунке ниже схематически показано распределение памяти для вложенной таблицы (плотной и разреженной). Пространство элементов черного цвета обозначает пустой элемент в коллекции, т.е. разреженный.

индекс 1 2 3 4 5 6 7
Значение (плотное) Xyz Дфв Сде Cxs ВВС Nhu Qwe
Значение (редкое) Qwe ASD афг ASD Кто

Синтаксис вложенной таблицы:

TYPE <tvpe name> IS TABLE OF <DATA TYPE>;
  • В приведенном выше синтаксисе имя_типа объявлено как коллекция вложенных таблиц типа «DATA_TYPE». Тип данных может быть простым или сложным.

Индекс по таблице

Индекс по таблице — это коллекция, в которой размер массива не фиксирован. В отличие от других типов коллекций, в коллекции индексов по таблицам индекс может определяться пользователем. Ниже приведены атрибуты индекса по таблице.

  • Индекс может быть целым числом или строкой. При создании коллекции следует указать тип индекса.
  • Эти коллекции не сохраняются последовательно.
  • В природе они всегда редки.
  • Размер массива не фиксирован.
  • Их нельзя хранить в столбце базы данных. Они должны создаваться и использоваться в любой программе в этом конкретном сеансе.
  • Они дают больше гибкости с точки зрения поддержания индекса.
  • Индексы также могут иметь отрицательную индексную последовательность.
  • Их более целесообразно использовать для относительно небольших коллективных значений, в которых коллекция может быть инициализирована и использована в одних и тех же подпрограммах.
  • Их не нужно инициализировать перед началом использования.
  • Его нельзя создать как объект базы данных. Его можно создать только внутри подпрограммы и использовать только в этой подпрограмме.
  • BULK COLLECT нельзя использовать в этом типе коллекции, поскольку нижний индекс должен указываться явно для каждой записи в коллекции.

На рисунке ниже схематически показано распределение памяти для вложенной таблицы (разреженной). Пространство элементов черного цвета обозначает пустой элемент в коллекции, т.е. разреженный.

Индекс (varchar) ПЕРВЫЙ ВТОРОЙ ТРЕТИЙ ЧЕТВЕРТЫЙ ПЯТЫЙ ШЕСТОЙ СЕДЬМОЙ
Значение (редкое) Qwe ASD афг ASD Кто

Синтаксис для индексирования по таблице

TYPE <type_name> IS TABLE OF <DATA_TYPE> INDEX BY VARCHAR2 (10);
  • В приведенном выше синтаксисе имя_типа объявлено как коллекция индексов по таблицам типа «DATA_TYPE». Тип данных может быть простым или сложным. Переменная subsciprt/index имеет тип VARCHAR2 с максимальным размером 10.

Конструктор и концепция инициализации в коллекциях

Конструкторы — это встроенные функции, предоставляемые оракулом и имеющие то же имя, что и объект или коллекции. Они выполняются первыми всякий раз, когда объект или коллекции обращаются впервые в сеансе. Ниже приведены важные детали конструктора в контексте коллекции:

  • Для коллекций эти конструкторы должны вызываться явно для их инициализации.
  • Таблицы Varray и Nested должны быть инициализированы с помощью этих конструкторов, прежде чем они будут переданы в программу.
  • Конструктор неявно расширяет выделение памяти для коллекции (кроме Varray), поэтому конструктор также может назначать переменные коллекциям.
  • Присвоение значений коллекции через конструкторы никогда не сделает коллекцию разреженной.

Методы сбора

Oracle предоставляет множество функций для манипулирования и работы с коллекциями. Эти функции очень полезны в программе для определения и изменения различных атрибутов коллекций. Следующая таблица даст различные функции и их описание.

Способ доставки Описание СИНТАКСИС
СУЩЕСТВУЕТ (н) Этот метод вернет логические результаты. Он вернет «ИСТИНА», если nth элемент существует в этой коллекции, иначе он вернет FALSE. В неинициализированной коллекции можно использовать только функции EXISTS. .EXISTS(позиция_элемента)
СЧИТАТЬ Возвращает общее количество элементов, присутствующих в коллекции. .СЧИТАТЬ
ОГРАНИЧЕНИЯ Возвращает максимальный размер коллекции. Для Varray он вернет определенный фиксированный размер. Для вложенной таблицы и индекса по таблице это дает NULL .LIMIT
ПЕРВЫЙ Возвращает значение первой индексной переменной (индекса) коллекций. .ПЕРВЫЙ
LAST Возвращает значение последней индексной переменной (индекса) коллекций. .ПОСЛЕДНИЙ
ПРИОР (н) Возвращаемые значения предшествуют индексной переменной в коллекции nth элемент. Если нет предшествующего индекса, возвращается значение NULL. .ПРИОР(н)
СЛЕДУЮЩИЙ (н) Возвращает успешную индексную переменную в коллекции nth элемент. Если нет успеха, возвращается значение индекса NULL. .ДАЛЕЕ(н)
ПРОДЛИТЕ Расширяет один элемент в коллекции в конце .ПРОДЛЕВАТЬ
ПРОДЛИТЬ (н) Расширяет n элементов в конце коллекции. .РАСШИРИТЬ(н)
РАСШИРИТЬ (n,i) Расширяет n копий ith элемент в конце коллекции .EXTEND(n,i)
TRIM Удаляет один элемент из конца коллекции .ПОДРЕЗАТЬ
ОБРЕЗКА (н) Удаляет n элементов из конца коллекции. .TRIM (н)
УДАЛИТЬ Удаляет все элементы из коллекции. Делает коллекцию пустой .УДАЛИТЬ
УДАЛИТЬ (н) Удаляет n-й элемент из коллекции. Если нth элемент равен NULL, то это ничего не даст .DELETE(н)
УДАЛИТЬ (м, н) Удаляет элемент в диапазоне mth к nth в коллекции .DELETE(м,п)

Пример 1: Тип записи на уровне подпрограммы

В этом примере мы увидим, как заполнить коллекцию, используя 'ОПТОВЫЙ СБОР' и как ссылаться на данные коллекции.

Тип записи на уровне подпрограммы

DECLARE
TYPE emp_det IS RECORD
(
EMP_NO NUMBER,
EMP_NAME VARCHAR2(150),
MANAGER NUMBER,
SALARY NUMBER
);
TYPE emp_det_tbl IS TABLE OF emp_det; guru99_emp_rec emp_det_tbl:= emp_det_tbl(); 
BEGIN
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1000,’AAA’,25000,1000);
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1001,'XXX’,10000,1000);
INSERT INTO emp (emp_no, emp_name, salary, manager) VALUES (1002,'YYY',15000,1000);
INSERT INTO emp (emp_no,emp_name,salary, manager) VALUES (1003,’ZZZ’,'7500,1000);
COMMIT:
SELECT emp no,emp_name,manager,salary BULK COLLECT INTO guru99_emp_rec
FROM emp;
dbms_output.put_line (‘Employee Detail');
FOR i IN guru99_emp_rec.FIRST..guru99_emp_rec.LAST
LOOP
dbms_output.put_line (‘Employee Number: '||guru99_emp_rec(i).emp_no); 
dbms_output.put_line (‘Employee Name: '||guru99_emp_rec(i).emp_name); 
dbms_output.put_line (‘Employee Salary:'|| guru99_emp_rec(i).salary); 
dbms_output.put_line(‘Employee Manager Number:'||guru99_emp_rec(i).manager);
dbms_output.put_line('--------------------------------');
END LOOP;
END;
/

Пояснение к коду:

  • Строка кода 2–8: Тип записи 'emp_det' объявляется со столбцами emp_no, emp_name, зарплата и менеджер типа данных NUMBER, VARCHAR2, NUMBER, NUMBER.
  • Строка кода 9: Создание коллекции emp_det_tbl элемента типа записи emp_det.
  • Строка кода 10: Объявление переменной «guru99_emp_rec» как типа «emp_det_tbl» и инициализация нулевым конструктором.
  • Строка кода 12–15: Вставка образца данных в таблицу emp.
  • Строка кода 16: Завершение транзакции вставки.
  • Строка кода 17: Получение записей из таблицы «emp» и массовое заполнение переменной коллекции с помощью команды «BULK COLLECT». Теперь переменная «guru99_emp_rec» содержит все записи, присутствующие в таблице «emp».
  • Строка кода 19–26: Настройка цикла FOR для печати всех записей в коллекции одна за другой. Методы сбора FIRST и LAST используются в качестве нижнего и верхнего предела поиска.

Результат: Как вы можете видеть на скриншоте выше, при выполнении приведенного выше кода вы получите следующий результат:

Employee Detail
Employee Number: 1000
Employee Name: AAA
Employee Salary: 25000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1001
Employee Name: XXX
Employee Salary: 10000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1002
Employee Name: YYY
Employee Salary: 15000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1003
Employee Name: ZZZ
Employee Salary: 7500
Employee Manager Number: 1000
----------------------------------------------