Разница между языком sql и языком plpgsql в функциях PostgreSQL

Я очень новичок в разработке баз данных, поэтому у меня есть некоторые сомнения относительно моего следующего примера:

Функция f1() - язык sql

 create or replace function f1(istr  varchar) returns text as $$ 
 select 'hello! '::varchar || istr;
 $$ language sql;

Функция f2() - язык plpgsql

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin select 'hello! '::varchar || istr; end;
 $$ language plpgsql;
  • Обе функции можно назвать как select f1('world') или же select f2('world'),

  • Если я позвоню select f1('world') вывод будет:

    `hello! world`
    
  • И выход для select f2('world'):

    ОШИБКА: у запроса нет места назначения для данных результата. СОВЕТ: Если вы хотите отменить результаты SELECT, используйте вместо этого PERFORM. КОНТЕКСТ: PL/pgSQL функция f11(символьная) строка 2 в операторе SQL ****** Ошибка ******

  • Я хочу знать разницу и в каких ситуациях я должен использовать language sql или же language plpgsql,

Любая полезная ссылка или ответы относительно функций будут высоко оценены.

3 ответа

Решение

Функции SQL

лучший выбор:

  • Для простых скалярных запросов. Не много планировать, лучше сэкономить на накладных расходах.

  • Для одиночных звонков за сеанс. Ничего не выиграет от планового кэширования и подготовленных операторов, которые может предложить PL / pgSQL. Увидеть ниже.

  • Если они обычно вызываются в контексте больших запросов и достаточно просты, чтобы быть встроенными.

  • Из-за отсутствия опыта работы с любым процедурным языком, таким как PL / pgSQL. Многие хорошо знают SQL, и это все, что вам нужно для функций SQL. Немногие могут сказать то же самое о PL / pgSQL.

  • Немного короче код Нет накладных расходов блока.

PL / pgSQL функции

лучший выбор:

  • Когда вам нужны какие-либо процедурные элементы или переменные, которые недоступны в функциях SQL, очевидно.

  • Для любого вида динамического SQL, где вы строите и EXECUTEзаявления динамически. Особая осторожность необходима, чтобы избежать внедрения SQL. Больше деталей:

  • Если у вас есть вычисления, которые можно использовать повторно в нескольких местах, и CTE не может быть растянут для этой цели. В функции SQL у вас нет переменных, и вам придется многократно вычислять или записывать в таблицу. Этот связанный ответ на dba.SE содержит примеры кода для решения той же проблемы с использованием функции SQL / функции plpgsql / запроса с CTE:

    Назначения несколько дороже, чем в других процедурных языках. Адаптируйте стиль программирования, который не использует больше назначений, чем необходимо.

  • Когда функция не может быть встроена и вызывается повторно. В отличие от функций SQL, планы запросов могут кэшироваться для всех операторов SQL внутри функций PL / pgSQL; они обрабатываются как подготовленные операторы, план кэшируется для повторных вызовов в пределах одного и того же сеанса (если Postgres ожидает, что кэшированный (универсальный) план будет работать лучше, чем перепланирование каждый раз. Именно поэтому функции PL / pgSQL обычно быстрее после первая пара звонков в таких случаях.

    Вот ветка о pgsql-performance, обсуждающая некоторые из этих пунктов:
    Re: pl / pgsql функции превосходят SQL?

  • Когда вам нужно ловить ошибки.

  • Для триггерных процедур (которые тоже просто функции).

  • При включении операторов DDL изменение объектов или изменение системных каталогов любым способом, относящимся к последующим командам - ​​поскольку все операторы в функциях SQL анализируются одновременно, в то время как функции PL / pgSQL планируют и выполняют каждый оператор последовательно (как подготовленный оператор). Увидеть:

Также учтите:


Для полноты: чтобы фактически вернуться из функции PL / pgSQL, вы можете написать:

CREATE FUNCTION f2(istr varchar)
  RETURNS text AS
$func$
BEGIN
   RETURN 'hello! ';  -- defaults to type text anyway
END
$func$ LANGUAGE plpgsql;

Есть и другие способы:

PL/PgSQL - это процедурный язык для PostgreSQL, основанный на SQL. Он имеет циклы, переменные, обработку ошибок / исключений и т. Д. Не весь SQL является допустимым PL/PgSQL - как вы обнаружили, например, вы не можете использовать SELECT без INTO или же RETURN QUERY, PL/PgSQL также может использоваться в DO блоки для одноразовых процедур.

sql функции могут использовать только чистый SQL, но они часто более эффективны и их проще писать, потому что вам не нужно BEGIN ... END; блок и т. д. Функции SQL могут быть встроенными, что не верно для PL/PgSQL.

Люди часто используют PL/PgSQL, где достаточно простого SQL, потому что они привыкли мыслить процедурно. В большинстве случаев, когда вы думаете, что вам нужен PL/PgSQL, вы, вероятно, на самом деле этого не делаете. Рекурсивные CTE, боковые запросы и т. Д. Обычно отвечают большинству потребностей.

Для получения дополнительной информации... см. Руководство.

Просто сделайте запрос на выборку, который вы написали внутри функции, как возвращаемое значение:

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin return(select 'hello! '::varchar || istr); end;
 $$ language plpgsql;
Другие вопросы по тегам