Функции PL / PgSQL и обычный SQL являются частью большего набора инструментов и должны рассматриваться в этом контексте. Я склонен думать об этом с точки зрения возрастающей шкалы мощности в сочетании с возрастающей сложностью и стоимостью, где вы должны использовать самый простой инструмент, который хорошо справится с работой:
- Используйте представления, где это возможно
- Там, где представление не подходит, используйте функцию SQL
- Если функция SQL не подходит, используйте PL / PgSQL.
- Там, где PL / PgSQL слишком ограничен или недостаточно выразителен, используйте PL / Perl, PL / Python, PL / V8, PL / Java, или как вы предпочитаете
- ... и там, где ни один PL не будет выполнять работу, использовать внешнюю программу и, возможно,
LISTEN
и NOTIFY
поговорить с ней.
Очень часто представление достаточно, когда вы думаете, что нужна функция. Даже если это очень дорого для SELECT
всего представления, WHERE
предложения в запросе, ссылающиеся на представление, обычно выталкиваются вниз в представление и могут привести к очень разным планам запросов. У меня часто были большие улучшения производительности от преобразования функций SQL в представления.
Основное время, когда вы обнаружите, что не можете использовать представление и должны рассмотреть функцию SQL, это когда:
- Необходимы параметры, которые не могут быть выражены в виде простых
WHERE
предложений, например, параметр в WITH
выражении
- Вам нужен защитный барьер через
SECURITY DEFINER
функцию, и security_barrier
представления в PostgreSQL 9.2 и выше не подходят для ваших нужд;
- Вам нужны параметры, которые не помещаются оптимизатором в подпункты представления, и вы хотите управлять им более непосредственно; или
- Есть много параметров или много повторений параметров, поэтому нецелесообразно писать запрос как представление.
Для большинства из этих задач простая функция SQL работает нормально, и ее часто легче читать, чем PL / PgSQL. Функции SQL, объявленные STABLE
или IMMUTABLE
(и не объявленные STRICT
или SECURITY DEFINER
), также могут быть встроены в вызывающий оператор. Это избавляет от накладных расходов, связанных с вызовом функции, и иногда может привести к огромным выигрышам в производительности, когда условие WHERE в вызывающей функции помещается оптимизатором в функцию SQL. Используйте функции SQL всякий раз, когда они достаточны для задачи.
Основное время, когда функции SQL не справляются с этой задачей, - это когда вам нужно много логики. Если / то / еще операции, которые вы не можете выразить как CASE
операторы, многократное использование вычисленных результатов, построение значений на основе кусков, обработка ошибок и т. Д. PL / PgSQL пригодится тогда. Выбирайте PL / PgSQL, когда вы не можете использовать функции SQL или они плохо подходят, например, для:
- Динамический SQL и динамический DDL через
EXECUTE
оператор
- Когда вы хотите, чтобы
RAISE
ошибки / предупреждения для журналов или клиента
- Когда вам нужна обработка исключений - вы можете перехватывать и обрабатывать ошибки с
EXCEPTION
блоками, вместо того, чтобы вся транзакция завершалась при ошибке
- Сложная условная логика, которая не
CASE ... WHEN
очень хорошо подходит
- Много повторного использования вычисленных значений, которые вы не можете вписать в
WITH
CTE и
- Построение динамических записей
- Вам необходимо выполнить действие после создания набора результатов
С общими табличными выражениями (CTE), особенно написанными CTE, и WITH RECURSIVE
я обнаружил, что я использую PL / PgSQL гораздо меньше, чем раньше, потому что SQL намного более выразителен и мощен. Сейчас я использую представления и простые функции SQL гораздо чаще. Стоит помнить, что простые функции SQL могут содержать более одного оператора; последнее утверждение является результатом функции.