PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

41.2. PL/pgSQL 的基本结构 #

用 PL/pgSQL 编写的函数是通过执行 CREATE FUNCTION 命令向服务器定义的。 这样一条命令通常看起来像这样:

CREATE FUNCTION somefunc(integer, text) RETURNS integer
AS 'function body text'
LANGUAGE plpgsql;

就 CREATE FUNCTION 而言,函数体只是一个字符串字面值。 使用美元符引用(见 Section 4.1.2.4) 来书写函数体通常比使用普通的单引号语法更有帮助。如果不使用美元符引用, 函数体中的任何单引号或反斜线都必须通过加倍来转义。 本章几乎所有示例的函数体都使用美元符引用的字面值。

PL/pgSQL 是一种块结构语言。 函数体的完整文本必须是一个块。 块的定义如下:

[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
END [ label ];

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

Tip

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

只有当你想在 EXIT 语句中标识这个块, 或者需要限定块中声明的变量的名字时,才需要 label(标签)。如果标签写在 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;

Note

实际上,在任何 PL/pgSQL 函数体周围都存在一个 隐藏的“外层块”。这个块提供了函数参数(如果有)的声明, 以及一些特殊变量,例如 FOUND(见 Section 41.5.5)。 外层块以函数名作为标签,这意味着参数和特殊变量 可以用函数名进行限定。

务必不要把 PL/pgSQL 中用于语句分组的 BEGIN/END 与名称相似的 SQL 事务控制命令混淆。PL/pgSQL 的 BEGIN/END 只用于分组;它们不会开始或结束事务。 有关在 PL/pgSQL 中管理事务的信息, 参见 Section 41.8。 另外,包含 EXCEPTION 子句的块实际上会形成一个子事务, 它可以被回滚而不影响外层事务。更多相关信息见 Section 41.6.8。