Функции для работы с массивами, в т.ч. многомерными

Статья основана на двадцать седьмом видео из 31 темы курса SQL 2.0 — PL/pgSQL в PostgreSQL от Аристова Евгения, который является логическим продолжением курса SQL c 0. Ссылки на видео на платформах RUTUBE и VK video.

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

В прошлой статье мы разобрали обработка ошибок для DML команд и как получить информацию об ошибке.

Презентация и исходники доступны по ссылке.

Массивы

Это набор однотипных данных. Определение и доступ к элементам заключаются в квадратные скобки. Нумерация элементов идёт с 1.

Примеры одномерных массивов:

DECLARE
  -- Простые массивы
  numbers INTEGER[];
  names TEXT[];
  flags BOOLEAN[];

-- С инициализацией
  prices NUMERIC[] := ARRAY[10.5, 20.3, 15.7];
  cities TEXT[] := ARRAY['Москва', 'СПб', 'Казань'];

Массивы. Сложные типы

DECLARE
  -- Массивы дат
  dates DATE[] := ARRAY['2024-01-01', '2024-01-02'];

  -- Массивы JSON
  json_data JSON[] := ARRAY['{"name": "John"}', '{"name": "Jane"}']; 

  -- Массивы UUID
  uuids UUID[] := ARRAY[
    '550e8400-e29b-41d4-a716-446655440000'::uuid,
    'f47ac10b-58cc-4372-a567-0e02b2c3d479'::uuid
];

Массивы. Доступ

DECLARE
  fruits TEXT[] := ARRAY['яблоко', 'банан', 'апельсин'];
  first_fruit TEXT;
  last_fruit TEXT;
  sliced_fruits TEXT[];
BEGIN
  -- Доступ к элементам (индексация с 1)
  first_fruit := fruits[1];
  last_fruit := fruits[array_length(fruits, 1)];

  -- Изменение элементов
  fruits[2] := 'груша';

  -- Срез массива
  sliced_fruits := fruits[1:2]; -- ['яблоко', 'груша']

Функции для работы с массивами

-- Добавление элементов
numbers := array_append(numbers, 4); -- [1, 2, 3, 4]
numbers := array_prepend(0, numbers); -- [0, 1, 2, 3, 4]
numbers := array_cat(numbers, ARRAY[5, 6]); -- [0, 1, 2, 3, 4, 5, 6]

-- Удаление элементов
numbers := array_remove(numbers, 3); -- Удалить все 3
numbers := array_remove(numbers, 999); -- Ничего не изменится, так как массив меньшей длины

-- Фильтрация (через unnest)
SELECT ARRAY(SELECT unnest(numbers) WHERE unnest % 2 = 0)
INTO filtered_numbers;

Массивы. Доп.функции

-- Длина массива
result := array_length(arr, 1)::text; RETURN NEXT;

-- Поиск элемента
searched_index := array_position(arr, 8);
result := COALESCE(searched_index::text, 'не найден');

-- Содержит ли элемент
result := (5 = ANY(arr))::text;

-- Пересечение массивов
result := array_to_string(arr && ARRAY[3,7], ','); – не сработает, посмотрим на практике

-- Сортировка
sorted_arr := ARRAY(SELECT unnest(arr) ORDER BY 1);
result := array_to_string(sorted_arr, ',');

-- Реверс
reversed_arr := ARRAY(SELECT unnest(arr) ORDER BY ordinality DESC FROM unnest(arr) WITH ORDINALITY); – аналогично нерабочий код
result := array_to_string(reversed_arr, ',');

Многомерные массивы

Примеры двухмерных массивов:

DECLARE
  numbers INTEGER[][];
  names TEXT[][];

  -- доступ
i = numbers[1][1]

Трехмерных:
  numbers INTEGER[][][]; 
i = numbers[1][1][1]

Четырёх и т.д. аналогично

Цикл по элементам многомерного массива FOR

Цикл FOREACH очень похож на FOR. Отличие в том, что вместо перебора строк SQL- запроса происходит перебор элементов массива. Синтаксис цикла FOREACH:

[ <<метка>> ]
FOREACH цель [ SLICE размерность_массива] IN ARRAY выражение LOOP
операторы
END LOOP [ метка ];

Без указания SLICE, или если SLICE равен 0, цикл выполняется по всем элементам массива, полученного из выражения. Переменной цель последовательно присваивается каждый элемент массива и для него выполняется тело цикла.

Итоги

Массивы в PL/pgSQL — это мощный инструмент для:

  • Пакетной обработки данных
  • Динамических запросов с множественными условиями
  • Временного хранения наборов значений
  • Упрощения сложной логики

Особенности:

  • аффектит на производительность, особенно удаление элемента
  • прямой доступ без проверки value := my_array[100]; — может быть ошибка, если элемента нет или тип не совпадает
  • по факту дорого аннестить и собирать обратно — лучше напрямую с массивами работать

Больше примеров доступно на гитхабе и в видео.

В следующей статье мы разберём DML триггеры.


Опубликовано

в

Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

20 − 13 =