2024年9月26日:PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:开发版本
不受支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

41.2. PL/pgSQL 的结构 #

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>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
END [ label ];

块中的每个声明和每个语句都以分号结尾。出现在另一个块内的块必须在 END 后面有一个分号,如上所示;但是,结束函数体的最后一个 END 不需要分号。

提示

一个常见的错误是在 BEGIN 后面立即写一个分号。这是错误的,会导致语法错误。

仅当您希望标识块以供 EXIT 语句使用,或限定块中声明的变量的名称时,才需要标签。如果在 END 后给出标签,则它必须与块开头的标签匹配。

所有关键字都不区分大小写。标识符隐式转换为小写,除非用双引号括起来,就像在普通的 SQL 命令中一样。

注释在 PL/pgSQL 代码中的工作方式与在普通 SQL 中相同。双破折号 (--) 开始一个扩展到行尾的注释。一个 /* 开始一个扩展到匹配的 */ 出现的块注释。块注释可以嵌套。

块的语句部分中的任何语句都可以是子块。子块可用于逻辑分组或将变量本地化到一小部分语句。在子块的持续时间内,在子块中声明的变量会屏蔽任何类似命名的外部块变量;但是,如果您使用其块的标签限定其名称,则仍然可以访问外部变量。例如

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/pgSQLBEGIN/END 仅用于分组;它们不会启动或结束事务。有关在 PL/pgSQL 中管理事务的信息,请参见 第 41.8 节。此外,包含 EXCEPTION 子句的块有效地构成一个可以回滚而不会影响外部事务的子事务。有关更多信息,请参见 第 41.6.8 节

提交更正

如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步澄清的内容,请使用 此表单 报告文档问题。