Postgresql 中文操作指南

43.2. Structure of PL/pgSQL #

通过执行 CREATE FUNCTION 命令向服务器定义使用 PL/pgSQL 编写的函数。这样的命令通常看起来像,比方说

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

对于_CREATE FUNCTION_,函数体只是一个字符串文本。通常使用美元引用(见 Section 4.1.2.4)编写函数体,而不是普通的单引号语法很有帮助。如果没有美元引用,函数体中的任何单引号或反斜杠都必须通过双写来转义。本章中几乎所有示例都使用美元引用文本作为它们的函数体。

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

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

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

Tip

一个常见的错误是在 BEGIN 之后立即写分号。这是不正确的,将导致语法错误。

只有当您希望为 EXIT 语句中使用而标示块,或对块中声明的变量的名称进行限定时,才需要 label。如果在 END 后给出了标签,则它必须与块开始时的标签相匹配。

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

在 PL/pgSQL 代码中,注释的工作方式与普通 SQL 中相同。双破折号(—​)用于开始注释,该注释一直持续到该行的结尾。/ starts a block comment that extends to the matching occurrence of /。块注释可嵌套。

块的语句部分中的任何语句都可以是一个 subblock。子块可用于逻辑分组或将变量定位到少量语句。在一个子块中声明的变量在该子块的持续时间内将屏蔽外部块的任何同名变量;但只要您用块的标签限定它们的名称,您仍然可以访问外部变量。例如:

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 43.5.5)。外部块标记有函数的名称,这意味着可以使用函数名称限定参数和特殊变量。

重要的是不要混淆使用_BEGIN_/END_来将 PL/pgSQL 中的语句分组与事务控制的相似名称的 SQL 命令。PL/pgSQL 的 _BEGIN/END 仅用于分组;它们不开始或结束事务。有关在 PL/pgSQL 中管理事务的信息,请参阅 Section 43.8。此外,包含_EXCEPTION_子句的块将有效地形成一个可以回滚的子事务,而不会影响外部事务。有关更多信息,请参阅 Section 43.6.8