40.2. PL/pgSQL的结构

PL/pgSQL是一种块结构的语言。 函数定义的所有文本都必须是一个块(block)。 可以用下面的方法定义一个块:

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

块中的每个声明和每条语句都是用一个分号终止的, 如果一个子块在另外一个块里,那么END后面必须有个分号,如上所述; 不过结束函数体的最后的END可以不要这个分号。

提示: 一个常见的错误是紧跟在BEGIN之后使用一个分号, 这是不正确的,并且会返回一个语法错误。

如果你想标记出在EXIT声明中的block,或者描述在block中所声明的变量名字, 此时,可以选择使用label。如果是在END之后给出一个标签,那么, 它必须与block开始时定义的标签相匹配。

所有的关键字都是不区分大小写的,正如在SQL命令中一样, 会隐式的将其转换成小写,除非是使用双引号。

如同在普通的SQL语句中一样,在PL/pgSQL代码中,用同样的方式定义注释: 在语句的最后,通过一个双破折号(--)来开始一条行注释。 而块注释是成对出现的, 通过/**/来定义。

块语句段里的任何语句都可以是一个子块。子块可以用于逻辑 分组或者把变量局部化为作用于一个较小的语句组。为了子块的持续时间任何同样命名的外部子块的变量在子块中声明变量, 但是如果你符合它们的名字和它们子块标签,无论如何你可以访问外部变量,比如:

CREATE FUNCTION somefunc() RETURNS integer AS $$
<< outerblock >>
DECLARE
    quantity integer := 30;
BEGIN
    
RAISE NOTICE 'Quantity here is %', quantity;  -- 在这里的数量是30
    quantity := 50;
    --
-- 创建一个子块
    --
    DECLARE
        quantity integer := 80;
    BEGIN
    
RAISE NOTICE 'Quantity here is %', quantity;  -- 在这里的数量是80
        RAISE NOTICE 'Outer quantity here is %', outerblock.quantity;  -- 在这里的数量是50
    END;
    
RAISE NOTICE 'Quantity here is %', quantity;  -- 在这里的数量是50

    RETURN quantity;
END;
$$ LANGUAGE plpgsql;

注意: 在任何PL/pgSQL函数主体周围有隐藏的"外部块"。 这个块提供了函数参数的声明(如果有),以及一些特殊变量比如 FOUND (参阅第 40.5.5 节)。 外部块可以使用函数的名字标记,意味着参数和特殊变量可以满足函数名字。

一定不要把PL/pgSQL里用于语句分组的BEGIN/END和用于事务控制的数据库命令搞混了。 PL/pgSQLBEGIN/END只是用于分组;它们不会开始和结束一个事务。 函数和触发器过程总是在一个由外层命令建立起来的事务里执行, 它们无法开始或者提交事务,因为PostgreSQL没有嵌套事务。 不过,一个包含EXCEPTION子句的块实际上形成一个子事务, 它可以在不影响外层事务的情况下回滚。更多相关信息请参阅第 40.6.6 节