↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 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 / 7.1
历史版本PostgreSQL 7.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

第 19 章 PL/pgSQL - SQL 过程语言

PL/pgSQL 是一种用于 PostgreSQL 数据库系统的可载入过程语言。

本包最初由 Jan Wieck 编写。本文档部分由 Roberto Mello ()编写。

19.1. 概述 #

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

  • 可以用于创建函数和触发器过程,

  • 为 SQL 语言增加控制结构,

  • 可以执行复杂计算,

  • 继承所有用户定义的类型、函数和操作符,

  • 可以定义为被服务器信任,

  • 易于使用。

PL/pgSQL 调用处理器在函数第一次被调用时(在任一 后端进程内)解析函数的源文本,并生成一棵内部二进制指令树。这棵指令树 完整地翻译了 PL/pgSQL 的语句结构,但函数中 使用的各个 SQL 表达式和 SQL 查询 并不会立即翻译。

当每个表达式和 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';

如果你执行上面的函数,它会在为 PERFORM 语句生成的查询计划中引用 my_function() 的 OID。之后,如果你删除并重新创建 my_function(),那么 populate() 将再也找不到 my_function() 了。此时你必须重新创建 populate(),或者至少启动一个新的数据库会话,使它 得以重新编译。

由于 PL/pgSQL 以这种方式保存执行计划,直接 出现在 PL/pgSQL 函数中的查询在每次执行时都 必须引用相同的表和字段;也就是说,你不能在查询中把参数用作表名或字段 名。要绕过这一限制,可以用 PL/pgSQL 的 EXECUTE 语句构造动态查询——代价是每次执行都要构造一个新的查询计划。

注意

PL/pgSQL 的 EXECUTE 语句与 PostgreSQL 后端支持的 EXECUTE 语句无关。 后端的 EXECUTE 语句不能在 PL/pgSQL 函数中 使用(也不需要)。

除了用户定义类型的输入/输出转换和计算函数之外,凡是可以用 C 语言函数 定义的事情,也都可以用 PL/pgSQL 完成。可以 创建复杂条件计算函数,之后用它们定义操作符或在函数索引中使用。

19.1.1. 使用 PL/pgSQL 的优点 #

19.1.1.1. 更好的性能 #

SQL 是 PostgreSQL(以及大多数其他 关系数据库)用作查询语言的语言。它可移植且易学。但每条 SQL 语句都必须由数据库服务器逐条执行。

这意味着你的客户端应用程序必须把每个查询发送到数据库服务器,等待其 处理,接收结果,做一些计算,然后再向服务器发送其他查询。所有这些都 会产生进程间通信开销;如果你的客户端与数据库服务器不在同一台机器上, 还会产生网络开销。

使用 PL/pgSQL,你可以把一块计算和一系列 查询组合在数据库服务器内部,从而既拥有过程语言的 能力,又拥有 SQL 的易用性,同时因为省去了整个客户端/服务器通信开销而 节省大量时间。这可以带来可观的性能提升。

19.1.1.2. SQL 支持 #

PL/pgSQL 为 SQL 的灵活和易用增添了过程语言的能力。使用 PL/pgSQL 可以使用 SQL 的所有数据类型、列、 操作符和函数。

19.1.1.3. 可移植性 #

由于 PL/pgSQL 函数运行在 PostgreSQL 内部,这些函数可以在 PostgreSQL 运行的任何平台上运行。因此你可以重用代码 并降低开发成本。

19.1.2. 在 PL/pgSQL 中开发 #

在 PL/pgSQL 中开发相当直接,尤其是如果你曾 用其他数据库过程语言(如 Oracle 的 PL/SQL)开发过。在 PL/pgSQL 中开发的两种好方法是:

  • 使用文本编辑器并用 psql 重新装载文件

  • 使用 PostgreSQL 的 GUI 工具: PgAccess

在 PL/pgSQL 中开发的一个好方法是,直接用你选定的文本 编辑器创建函数,同时在另一个窗口用 psql (PostgreSQL 的交互监视器)装载这些函数。如果你这样做, 最好用 CREATE OR REPLACE FUNCTION 编写函数。这样 只需重新装载文件即可更新函数定义。例如:

CREATE OR REPLACE FUNCTION testfunc(INTEGER) RETURNS INTEGER AS '
          ....
end;
' LANGUAGE 'plpgsql';

在运行 psql 期间,可以用

    \i filename.sql

装载或重新装载这样的函数定义文件,然后立即发出 SQL 命令来测试该函数。

在 PL/pgSQL 中开发的另一个好方法是使用 PostgreSQL 的 GUI 工具:PgAccess。 它会为你做一些好事,比如转义单引号、让重新创建和调试函数变得容易。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。