Чтобы использовать **PL/Python**, необходимо, чтобы модуль Python был установлен в вашей операционной системе для вашей версии PostgreSQL (например, пакет `postgresql-plpython3` в Linux), после чего его можно включить в нужной базе данных.
#### 1. Активация PL/Python
Активировать расширение нужно в целевой базе данных от имени суперпользователя (`postgres`):
**Важная деталь:** Буква `u` на конце расширения означает *untrusted* (недоверенный). Это значит, что функции на PL/Python могут обращаться к файловой системе сервера, сети и операционной системе, поэтому создавать функции на PL/Python может только суперпользователь СУБД.
#### 2. Пример функции (Function)
Функции в PostgreSQL возвращают значение. В PL/Python вы можете импортировать любые сторонние библиотеки Python (например, `json`, `math`, `requests`, `pandas` и др.).
Пример функции для парсинга и валидации JSON-строки с расчетом итоговой стоимости:
Процедуры в PostgreSQL не возвращают результат и поддерживают управление транзакциями (`plpy.commit()`, `plpy.rollback()`).
Специальный модуль `plpy` внутри PL/Python позволяет выполнять SQL-запросы внутри базы.
Пример процедуры, которая находит устаревшие записи, отправляет их во внешнюю систему (имитация) и удаляет их:
Внутри PL/Python вам автоматически доступен встроенный объект `plpy`:
-
`plpy.execute("SELECT ...")` — выполнение произвольного SQL-запроса.
-
`plpy.prepare(query, [types])` — подготовка SQL-запроса для многократного выполнения.
-
`plpy.notice(msg)`, `plpy.info(msg)`, `plpy.warning(msg)` — вывод сообщений пользователю.
-
`plpy.error(msg)` — генерация исключения, отменяющего транзакцию.
### Возвращают ли функции PL/Python наборы строк (recordsets) которые можно использовать в SQL-запросах?
**Да, функции PL/Python могут возвращать наборы строк.** Их можно использовать непосредственно в блоке `FROM` SQL-запроса, как обычную таблицу или представление (View).
Возвращать наборы данных из PL/Python можно двумя основными способами:
1.
**Список словарей / списков / кортежей** — если функция формирует и отдает все данные сразу.
2.
**Итератор / Генератор (`yield`)** — если данных много и их нужно отдавать по одной строке (ленивые вычисления), чтобы не перегружать оперативную память.
#### Вариант 1. Возврат всех строк через список (List of Dicts)
Для возврата таблицы используется конструкция `RETURNS TABLE(...)` или `RETURNS SETOF record_type`. Внутри Python-кода вы возвращаете обычный список Python-словарей, где ключи соответствуют именам колонок.
Если функция должна выгрузить 100 000+ строк из внешнего ресурса, сохранение их всех в список в памяти вызовет высокую нагрузку на RAM. В PL/Python можно использовать встроенный оператор Python `yield`.
Если функция выполняет внутренний SQL-запрос с помощью `plpy.execute()`, возвращаемый объект `PLPyResult` уже является итерируемым набором строк, поэтому его можно вернуть напрямую: