PL/pgSQL 中编写的函数通过执行 CREATE FUNCTION 命令在服务器上定义。这样的命令通常会类似于:
CREATE FUNCTION somefunc(integer, text) RETURNS integer
AS 'function body text
'
LANGUAGE plpgsql;
对于 CREATE FUNCTION
来说,函数体只是一个字符串字面值。使用美元符引用(参见 第 4.1.2.4 节)来编写函数,而不是使用普通单引号语法,通常很有帮助。如果不使用美元符引用,函数体中的任何单引号或反斜杠都必须通过加倍转义。本章中的几乎所有示例都使用美元符引用字面值作为函数体。
PL/pgSQL 是一种块结构化语言。函数体的全部文本必须是 块。块定义为:
[ <<label
>> ] [ DECLAREdeclarations
] BEGINstatements
END [label
];
块中每个声明和每个语句都以分号终止。显示在另一个块中的块必须在 END
后面有一个分号,如上所示;但是,结束函数体的最终 END
不需要分号。
一个常见的错误是在 BEGIN
后直接写一个分号。这是错误的,会导致语法错误。
仅在您想要标识块以便在 EXIT
语句中使用,或限定在块中声明的变量的名称时,才需要 label
。如果在 END
后给出了标签,它必须与块开头的标签匹配。
所有关键字不区分大小写。标识符会隐式转换为小写(除非使用双引号),就像在普通 SQL 命令中一样。
PL/pgSQL 代码中的注释与普通 SQL 中的注释的工作方式相同。双破折号 (--
) 开始一个注释,该注释一直持续到该行的结尾。/*
开始一个块注释,该块注释一直持续到匹配的 */
。块注释可以嵌套。
块的 statement 段中的任何语句都可以是 子块。子块可用于逻辑分组或将变量本地化到一小组语句。在子块中声明的变量会在子块持续期间屏蔽外表块的任何同名变量;但是,如果您使用块的标签限定其名称,则您可以随时访问外部变量。例如:
CREATE FUNCTION somefunc() RETURNS integer AS $$ << outerblock >> DECLARE quantity integer := 30; BEGIN RAISE NOTICE 'Quantity here is %', quantity; -- Prints 30 quantity := 50; -- -- Create a subblock -- DECLARE quantity integer := 80; BEGIN RAISE NOTICE 'Quantity here is %', quantity; -- Prints 80 RAISE NOTICE 'Outer quantity here is %', outerblock.quantity; -- Prints 50 END; RAISE NOTICE 'Quantity here is %', quantity; -- Prints 50 RETURN quantity; END; $$ LANGUAGE plpgsql;
实际上,任何 PL/pgSQL 函数的主体周围都有一个隐式的 “外部块”。该块提供函数参数的声明(如有),以及一些特殊变量,如 FOUND
(请参见 第 41.5.5 节)。外部块用函数的名称标记,这意味着可以通过函数名称限定参数和特殊变量。
注意不要将 PL/pgSQL 中用于对语句进行分组的 BEGIN
/END
用法与用于事务控制的同名 SQL 命令混淆。 PL/pgSQL 中的 BEGIN
/END
仅用于分组;不会启动或结束事务。有关在 PL/pgSQL 中管理事务的信息,请参见 第 41.8 节。此外,包含 EXCEPTION
子句的块实际上会形成一个子事务,该事务可以回滚而不影响外部事务。有关更多信息,请参见 第 41.6.8 节。