PostgreSQL函数中语言sql和语言plpgsql的区别

37 sql postgresql stored-procedures function plpgsql

我是数据库开发的新手,所以我对以下示例有些怀疑:

函数f1() - 语言sql

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

函数f2() - 语言plpgsql

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin select 'hello! '::varchar || istr; end;
 $$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
  • 这两个函数都可以像select f1('world')或一样调用select f2('world').

  • 如果我打电话select f1('world')输出将是:

    `hello! world`
    
    Run Code Online (Sandbox Code Playgroud)
  • 输出select f2('world'):

    错误:查询没有结果数据的目的地提示:如果要丢弃SELECT的结果,请改用PERFORM.语境:在SQL语句中PL/pgSQL函数f11(字符变化)第2行 ******错误******

  • 我想知道的差异,在哪些情况下我应该使用language sqllanguage plpgsql.

任何有用的链接或关于功能的答案将非常感谢.

Erw*_*ter 51

SQL函数

是更好的选择:

  • 对于简单的标量查询.计划不多,更好地节省开销.

  • 对于每个会话的单个呼叫.PL/pgSQL必须提供的计划缓存和准备好的声明无法获得任何好处.见下文.

  • 如果它们通常在较大查询的上下文中调用,并且足够简单以便内联.

  • 由于缺乏任何程序语言(如PL/pgSQL)的经验.许多人都熟悉SQL,这就是SQL函数所需要的.很少有人能说PL/pgSQL.

  • 一点点代码.没有块开销.

PL/pgSQL函数

是更好的选择:

  • 当您需要SQL函数中不可用的任何过程元素变量时,显然.

  • 对于任何类型的动态SQL,您EXECUTE可以动态地构建和声明.需要特别小心以避免SQL注入.更多细节:

  • 如果您有可以在多个地方重复使用的计算,并且无法为此目的拉伸CTE.在SQL函数中,您没有变量,将被强制重复计算或写入表.这个关于dba.SE的相关答案有一个并排的代码示例,用于使用SQL函数/一个plpgsql函数/一个CTE查询解决相同的问题:

    作业比其他程序语言更昂贵.调整不使用超出必要的分配的编程风格.

  • 当函数无法内联并重复调用时.与SQL函数不同,可以为PL/pgSQL函数内的所有SQL语句缓存查询计划 ; 它们被视为预处理语句,计划被缓存以便在同一会话中重复调用(如果Postgres希望缓存(通用)计划的执行效果优于每次重新计划.这就是PL/pgSQL函数通常更快的原因之后在这种情况下的第一个电话.

    这是一个关于pgsql-performance讨论其中一些项目的线程:
    Re:pl/pgsql函数优于sql函数吗?

  • 当您需要捕获错误时.

  • 对于触发程序(也只是函数).

  • 当包含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;
Run Code Online (Sandbox Code Playgroud)

还有其他方法:


Cra*_*ger 16

PL/PgSQL是一种基于SQL的PostgreSQL特定的过程语言.它有循环,变量,错误/异常处理等.并非所有的SQL是有效的PL/pgSQL的-因为你发现了,例如,你不能使用SELECT没有INTORETURN QUERY.PL/PgSQL也可以用于DO一次性程序的块.

sql函数只能使用纯SQL,但它们通常更高效,并且它们更易于编写,因为您不需要BEGIN ... END;块等.SQL函数可能是内联的,而PL/PgSQL则不然.

人们经常使用PL/PgSQL,其中普通的SQL就足够了,因为他们习惯于在程序上进行思考.在大多数情况下,当您认为自己需要PL/PgSQL时,实际上可能并非如此.递归CTE,横向查询等通常满足大多数需求.

有关详细信息,请参阅手册.

  • 确实,基于集合的解决方案通常更优越。但这并不是使用 SQL 还是 PL/pgSQL 函数的最终结论。新人有时会出于错误的原因使用 plpgsql。 (2认同)