Подтвердить что ты не робот

Разница между языком 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.        CONTEXT: функция PL/pgSQL f11 (переменная символов) строка 2 в операторе SQL         ****** Ошибка ******

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

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

4b9b3361

Ответ 1

Функции 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;

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

Ответ 2

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, боковые запросы и т.д. Обычно отвечают большинству потребностей.

Подробнее... см. руководство.

Ответ 3

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

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin return(select 'hello! '::varchar || istr); end;
 $$ language plpgsql;