В больших, объемных pl-процедурах бывают ситуации, когда по каким-либо причинам в нескольких местах приходится использовать одни и те же запросы и обрабатывать их результаты. Что-то похожее на двухпроходные алгоритмы - обработали данные, накопили результаты, повторно обработали те же данные - получили конечный результат. Если запросы выполняются быстро, то проблем нет, но ситуации бывают разные, и иногда хочется как-то сохранить результат выполнения запроса и использовать сохраненный результат в дальнейшем. Для хранения кода может отлично подойти массив записей. К примеру, имеется таблица customers
CREATE TABLE customers (
id int PRIMARY KEY,
name varchar NOT NULL UNUQUE
);
Надо закешировать запрос, который возвращает всех клиентов в имени которых есть буква z, так как запрос по ряду причин может выполнятся долго.
SELECT * FROM customers WHERE name ILIKE '%z%';
Для кеширования можно использовать следующий подход:
DECLARE
_customers customers[]; -- В этом массиве будет хранится результат выполнения запроса
_customer customers;
BEGIN
-- Функцию ARRAY удобно использовать, так как, если запрос не вернет ни одной строки, то результатом будет пустой
-- массив, а не значение NULL, если бы использовалась функция array_agg
_customers := ARRAY(SELECT c FROM customers AS c WHERE name ILIKE '%z%'); -- Закешировали результат запроса
FOR _customer IN SELECT * FROM unnest(_customers) -- Простое использование закешированного результата
LOOP
END LOOP;
FOR _customer IN SELECT * FROM unnest(_customers) WHERE id > 100 -- Закешированный результат можно дополнительно отфильтровать
LOOP
END LOOP;
END
Вот так всё просто.
Примечание
Кеширование больших выборок может потребовать много памяти, поэтому используйте кеш только в тех случаях, когда выигрыш в производительности действительно будет значительным.