PostgreSQL函数中的LANGUAGE SQL vs LANGUAGE plpgsql

2guxujil  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(4)|浏览(200)

我在 * 数据库开发 * 方面很新,所以我对下面的例子有一些疑问:
函数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')output

错误代码:查询没有结果数据的目标提示:如果要放弃SELECT的结果,请改用PERFORM。上下文:PL/pgSQL函数f11(字符变化)SQL语句第2行 * 错误**

  • 我想知道区别,以及在哪些情况下我应该使用language sqllanguage plpgsql

任何有用的链接或有关功能的答案将不胜感激。

q7solyqu

q7solyqu1#

SQL functions第一个字符

...是更好的选择:

  • 对于简单的标量查询。没有太多要计划的,最好保存任何开销。
  • 对于每个会话的单个(或很少)调用。通过PL/pgSQL必须提供的预处理语句从计划高速缓存中没有任何好处。请参阅下文。
  • 如果它们通常是在较大查询的上下文中调用的,并且足够简单,可以是inlined
  • 因为缺乏使用PL/pgSQL这样的过程语言的经验。很多人都很了解SQL,这就是使用SQL函数所需要的。很少有人能对PL/pgSQL说同样的话。(尽管它相当简单。)
  • 代码更短一点。没有块开销。

PL/pgSQL functions(第一对)

...是更好的选择:

  • 当您需要SQL函数中没有的任何过程元素变量时,很明显。
  • 适用于任何类型的动态SQL,其中您会动态建置和EXECUTE叙述句。需要特别注意,以避免SQL内建。详细信息:
  • Postgres functions vs prepared queries
  • 当您有可在多个地方重复使用计算,而CTE不能为此目的进行扩展时。在SQL函数中,您没有变量,因此将被迫重复计算或写入表。dba.SE上的相关答案提供了使用SQL函数/plpgsql函数/ a具有CTE的查询解决相同问题的并列代码示例
  • How to pass a parameter into a function

赋值比其他过程语言的开销要大一些,所以要采用一种不使用过多赋值的编程风格。

  • 当函数无法内联且被重复调用时。与SQL函数不同,查询计划可以为PL/pgSQL函数内的所有SQL语句进行高速缓存;它们被当作预准备语句来处理,为同一会话中的重复调用缓存计划(如果Posterre希望缓存的(通用)计划每次都比重新计划的性能更好。这就是PL/pgSQL函数 * 通常更快的原因 *)在这种情况下的第一对呼叫之后。

下面是一个关于pgsql-performance的线程,讨论了其中的一些项目:

  • 回复:pl/pgsql函数的性能优于sql函数?
  • 需要捕获错误时。
  • 对于trigger functions
  • 当包含DDL叙述句时,会以任何与后续命令相关的方式变更对象或系统目录,因为SQL函数中的所有叙述句会同时进行剖析,而PL/pgSQL函数则会依序规划和执行每个叙述句(如同准备的叙述句)。请参阅:
  • 为什么PL/pgSQL函数会有副作用,而SQL函数不会?

还应考虑:

要从PL/pgSQL函数中实际 return,可以编写以下语句:

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

字符串
还有其他方法:

  • 我可以让plpgsql函数在不使用变量的情况下返回一个整数吗?
  • “从函数返回”手册
koaltpgm

koaltpgm2#

PL/PgSQL is a PostgreSQL-specific procedural language based on SQL。它有循环,变量,错误/异常处理等。不是所有的SQL都是有效的PL/PgSQL -正如你所发现的,例如,你不能在没有INTORETURN QUERY的情况下使用SELECT。PL/PgSQL也可以在DO块中用于一次性过程。
sql functions只能使用纯SQL,但它们通常更有效,编写更简单,因为您不需要BEGIN ... END;块等。SQL函数可能是内联的,但PL/PgSQL不是这样。
人们经常使用PL/PgSQL,而普通SQL就足够了,因为他们习惯于按程序思考。在大多数情况下,当你认为你需要PL/PgSQL时,你可能实际上并不需要。递归CTE,横向查询等通常可以满足大多数需求。
有关更多信息,请参阅手册。

dddzy1tm

dddzy1tm3#

只需将您在函数中编写的select查询作为返回值:

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

字符串

qvsjd97n

qvsjd97n4#

A SQL function

  • 可以有零个或多个SQL查询,有或没有AS子句,或者BEGIN ATOMIC ... END clause从调用者那里获得零个或多个值,带有零个或多个参数。* BEGIN ATOMIC ... END子句根据the doc仅适用于LANGUAGE SQL
  • 可以有INOUTINOUTVARIADIC参数。* 我的答案解释了一个VARIADIC参数。
  • 不能有DECLARE clause,否则会有错误,而PL/pgSQL函数可以。
  • 可以有只有类型的参数。* 我的答案解释了这一点。
  • 可以有参数$1$2等的别名。* 我的答案解释了这一点。
  • 可以使用AS子句或BEGIN ATOMIC ... END子句将最后一个语句的值返回给具有SELECT statementRETURNING clause的调用者。
  • 可以使用RETURN语句将最后一个语句的值返回给调用者,而不是使用AS子句或BEGIN ATOMIC ... END子句。
  • 不能有BEGIN ... END子句,它可以有多个SQL查询,否则会有错误,而PL/pgSQL函数可以有它。* 小心,BEGIN ... END子句不是transaction
  • 默认情况下,在单个事务中运行的是原子的,因此如果有错误,它会自动回滚。
  • 无法控制START TRANSACTIONBEGINROLLBACKCOMMIT等的交易,否则会出现错误。
  • My post详细解释了一个SQL函数。

A PL/pgSQL function

  • 可以有零个或多个带有BEGIN ... END语句的SQL查询,从调用者那里获得零个或多个带有零个或多个参数的值。* 请注意,BEGIN ... END子句不是transaction
  • 可以有INOUTINOUTVARIADIC参数。* 我的答案解释了一个VARIADIC参数。
  • 可以有DECLARE clause,而SQL function不能。* 我的答案解释了如何用DECLARE子句声明局部变量。
  • 可以有只有类型的参数。* 我的答案解释了这一点。
  • 可以有参数$1$2等的别名。* 我的答案解释了这一点。
  • 可以有SELECT INTO statement
  • 可以使用PERFORM语句。
  • 不能有SELECT statement没有INTORETURNING clause否则有错误。
  • 可以使用RETURN语句、OUTINOUT参数返回一个值给调用者。
  • 默认情况下,在单个事务中运行的是原子的,所以如果有错误,它会自动回滚。
  • 无法控制START TRANSACTIONBEGINROLLBACKCOMMIT等的交易,否则会出错。
  • 类似于MySQL function
  • My post解释了PL/pgSQL函数。

相关问题