Функции 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очень хорошо подходит
- Много повторного использования вычисленных значений, которые вы не можете вписать в
WITHCTE и
- Построение динамических записей
- Вам необходимо выполнить действие после создания набора результатов
С общими табличными выражениями (CTE), особенно написанными CTE, и WITH RECURSIVEя обнаружил, что я использую PL / PgSQL гораздо меньше, чем раньше, потому что SQL намного более выразителен и мощен. Сейчас я использую представления и простые функции SQL гораздо чаще. Стоит помнить, что простые функции SQL могут содержать более одного оператора; последнее утверждение является результатом функции.