在数据库开发中非常新,所以我对以下示例有疑问:
功能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。 语境:SQL语句中的PL / pgSQL函数f11(字符变化)第2行 ****** 错误 ******
我希望了解差异,以及在哪种情况下我应该使用language sql
或language plpgsql
。
非常感谢有关功能的任何有用链接或答案。
答案 0 :(得分:44)
是更好的选择:
对于简单标量查询。计划不多,更好地节省开支。
对于每个会话的单个(或极少数)呼叫。通过PL / pgSQL提供的预准备语句从计划缓存中无法获得任何好处。见下文。
如果通常在更大的查询环境中调用它们,并且它们非常简单,可以inlined。
缺少体验与任何程序语言,如PL / pgSQL。许多人都熟悉SQL,并且了解SQL函数所需的全部内容。很少有人能说PL / pgSQL。 (虽然它很简单。)
更短的代码。没有阻止开销。
是更好的选择:
当您需要SQL功能中不可用的任何程序元素或变量时,显然。
对于任何类型的动态SQL ,您可以动态地构建和EXECUTE
语句。需要特别小心以避免SQL注入。更多细节:
如果计算可以在多个地方重复使用,则无法为此目的拉伸CTE。在SQL函数中,您没有变量,将被迫重复计算或写入表。这个关于dba.SE的相关答案有并排的代码示例,用于使用SQL函数/ plpgsql函数/ CTE查询来解决相同的问题:
作业比其他程序语言贵一些。适应不使用必要的更多作业的编程风格。
当函数无法内联并重复调用时。与SQL函数不同,query plans can be cached for all SQL statements inside a PL/pgSQL functions;它们被视为预备语句,计划被缓存以便在同一会话中重复调用(如果Postgres希望缓存(通用)计划的性能优于每次重新计划。)在这种情况下,在前几次调用之后PL / pgSQL函数 通常更快 的原因。
这是一个关于pgsql-performance的讨论其中一些项目的线程:
Re: pl/pgsql functions outperforming sql ones?
当您需要trap errors.
对于trigger procedures(它们也只是功能)。
当包含DDL语句以与后续命令相关的任何方式更改对象或更改系统目录时 - 因为PL / pgSQL函数计划并按顺序执行每个语句时,SQL函数中的所有语句都会被立即解析(如准备好的语句) )。参见:
还要考虑:
要从PL / pgSQL函数实际返回,您可以写:
CREATE FUNCTION f2(istr varchar)
RETURNS text AS
$func$
BEGIN
RETURN 'hello! '; -- defaults to type text anyway
END
$func$ LANGUAGE plpgsql;
还有其他方法:
答案 1 :(得分:14)
PL/PgSQL is a PostgreSQL-specific procedural language based on SQL。它有循环,变量,错误/异常处理等。并非所有SQL都是有效的PL / PgSQL - 例如,您发现,如果没有SELECT
或{{{{}}},则不能使用INTO
1}}。 PL / PgSQL也可以在RETURN QUERY
块中用于一次性程序。
sql
functions只能使用纯SQL,但它们通常效率更高,而且编写起来更简单,因为您不需要DO
块等。 SQL函数可能是内联的,而PL / PgSQL则不然。
人们经常使用PL / PgSQL,其中普通的SQL就足够了,因为他们习惯于在程序上进行思考。在大多数情况下,当你认为你需要PL / PgSQL时,你可能实际上并不是这样。递归CTE,横向查询等通常满足大多数需求。
有关详细信息,请参阅手册。
答案 2 :(得分:0)
只需使您在函数内部编写的选择查询作为返回值即可:
create or replace function f2(istr varchar)
returns text as $$
begin return(select 'hello! '::varchar || istr); end;
$$ language plpgsql;