Chapter 24. PL/pgSQL - SQL 过程语言

Table of Contents
24.1. 概述
24.1.1. 使用 PL/pgSQL 的优点
24.1.2. 用 PL/pgSQL 做开发
24.2. 描述
24.2.1. PL/pgSQL 的结构
24.2.2. 注释
24.2.3. 变量和内容
24.2.4. 表达式
24.2.5. 语句
24.2.6. 控制结构
24.2.7. 使用 RECORD
24.2.8. 退出和消息
24.2.9. 例外处理
24.3. 触发器过程
24.4. 例子
24.5. 从 Oracle 的 PL/SQL 向 PL/pgSQL移植
24.5.1. 主要的区别
24.5.2. 移植函数
24.5.3. 过程
24.5.4.
24.5.5. 其它要注意的东西
24.5.6. 附录

PL/pgSQL 是 Postgres 数据库系统的一个可装载的过程语言.

这个包最初是 Jan Wieck 写的. 这份文档的一部分是 Roberto Mello () 写的.

24.1. 概述

PL/pgSQL 的设计目标是创建一种可装载的过程语言,可以

PL/pgSQL 函数第一次被后端调用时, PL/pgSQL 的调用句柄分析函数源文本生成二进制指令树. 所生成的字节码在调用句柄里是用函数的对象标识来标记的. 这样就保证使用 DROP/CREATE 序列所做的修改 并不需要建立一个新的数据库联接就能生效.

对于函数里用到的所有表达式和 SQL 语句,PL/pgSQL 字节码解释器使用 SPI 管理器 SPI_prepare()SPI_saveplan()函数创建一个准备好了的执行规划. 这些动作是在(解析器)第一次处理 PL/pgSQL函数里面独立的语句时完成的. 因此,一个函数如果带有条件代码并且有许多语句 而且还需要执行规划, 那么将只准备和保存那些在整个数据库联接周期内真正使用到的规划.

这就意味着你必须小心谨慎地对待你的用户定义函数,比如∶

CREATE FUNCTION populate() RETURNS INTEGER AS '
DECLARE
    -- Declarations
BEGIN
    PERFORM my_function();
END;
' LANGUAGE 'plpgsql';
如果你创建了上面的函数,那么它将在自身的字节码中引用 my_function() 的 OID.然后,如果你 删除然后重新创建 my_function(), 那么 populate() 就会再也找不到 my_function().这时候你只能重新 创建 populate()

因为 Pl/pgSQL 用这种方法保存执行规划,所以那些在 PL/pgSQL 里直接 出现的查询必须在每次执行的时候引用相同的表和字段;也就是说, 你不能拿一个参数用做查询中的表或者字段的名称.要绕开这个限制, 你可以用 PL/pgSQL 的 EXECUTE 语句动态地构造查询 --- 代价是每次 执行的时候都构造一个新的查询计划.

除了用于用户定义类型的输入/输出转换和计算函数以外, 任何可以在 C 语言函数里定义的东西都可以在 PL/pgSQL 里使用. 我们可以创建复杂的条件计算函数, 并随后将之用于定义操作符或者用于函数索引中.

24.1.1. 使用 PL/pgSQL 的优点

24.1.1.1. 更好的性能

SQL 是 PostgreSQL(和大多数其它关系型数据库) 用做查询语言的语言.它是可以移植的,并且容易学习使用. 但是所有 SQL 语句都必须由数据库服务器 独立地执行.

这就意味着你的客户端应用必须把每条查询发送到数据库服务器, 等待它处理这个查询,接收结果,做一些运算,然后给服务器发送另外 一条查询.所有这些东西都会产生进程间通讯,并且如果你的 客户端在另外一台机器上甚至还会导致网络开销.

如果使用了 PL/pgSQL,那么你可以把一块运算和一系列查询 在数据库服务器里面组成一个块, 这样就拥有了过程语言的力量并且简化 SQL 的使用,因而 节约了大量的时间,因为你用不着付出客户端/服务器通讯的过热. 通过使用 PL/pgSQL,你的应用可以获得可观的性能提升.

24.1.1.2. SQL 支持

PL/pgSQL 在 SQL 灵活简单的基础上 为它增加了过程语言的能力.在 PL/pgSQL 里,你可以使用 所有数据类型,字段,操作符和 SQL 的函数.

24.1.1.3. 可移植性

因为 PL/pgSQL 函数在 PostgreSQL 内部运行, 这些函数将可以运行在任何 PostgreSQL 能够运行的机器上. 因此你可以复用代码并且减少开发费用.

24.1.2. 用 PL/pgSQL 做开发

用 PL/pgSQL 做开发是相当直接的,尤其是如果你已经用过 其它的数据库过程语言的情况下,比如 Oracle 的 PL/SQL 之类. 用 PL/pgSQL 做开发的两个好方法是∶

  • 使用一个文本编辑器并且用 psql 重载该文件

  • 使用 PostgreSQL 的 GUI 工具∶pgaccess

用 PL/pgSQL 做开发的一个好方法是简单地使用你喜欢的文本编辑器 创建你的函数,然后在另外一个控制台里,用 psql (PostgreSQL 的交互监控器)装载这些函数.如果你用这种方法(而且你 还是个新手或者在调试阶段),那么在创建你的函数之前总是先 DROP 你的函数是个好习惯.这样,在你重载你的 函数的时候,它就会删除你的函数然后重新创建它们.比如∶

drop function testfunc(integer);
create function testfunc(integer) return integer as '
    ....
end;
' language 'plpgsql';

在你第一次装载这个文件的时候,PostgreSQL 将抛出一个警告,说这个函数并不存在并且继续创建它.要装载 一个 SQL 文件(filename.sql)到名为"dbname"的数据库里, 用下面的命令∶

psql -f filename.sql dbname

另外一个开发 PL/pgSQL 程序的好方法是用 PostgreSQL 的 GUI 工具∶pgaccess. 它会为你做一些很有用的事情,比如逃逸单引号, 令重建和调试函数更简单等.