Разница между языком 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;