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

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
历史版本PostgreSQL 7.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

19.3. 声明 #

块中使用的所有变量、行和记录都必须在该块的声明区中声明。(唯一的 例外是,在整数值范围上迭代的 FOR 循环的循环变量会被自动声明为 integer 变量。)

PL/pgSQL 变量可以有任何 SQL 数据类型,例如 INTEGER、VARCHAR 和 CHAR。

下面是一些变量声明的例子:

user_id INTEGER;
quantity NUMERIC(5);
url VARCHAR;
myrow tablename%ROWTYPE;
myfield tablename.fieldname%TYPE;
arow RECORD;

变量声明的一般语法为:

name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT | := } expression ];

如果给出了 DEFAULT 子句,它指定进入块时赋给变量的初始值。如果没有 给出 DEFAULT 子句,变量被初始化为 SQL 空值。

CONSTANT 选项阻止对变量赋值,使其值在块的持续期间保持不变。如果 指定了 NOT NULL,赋予空值会导致运行时错误。所有声明为 NOT NULL 的变量都必须指定一个非空默认值。

默认值在每次进入块时求值。因此,例如把 'now' 赋给一个 timestamp 类型的变量,会使该变量具有当前函数 调用的时间,而不是函数预编译时的时间。

例子:

quantity INTEGER DEFAULT 32;
url varchar := ''http://mysite.com'';
user_id CONSTANT INTEGER := 10;

19.3.1. 函数参数的别名 #

name ALIAS FOR $n;

传递给函数的参数以标识符 $1、$2 等命名。可以选择为 $n 参数名声明别名以提高可读性。 之后既可以用别名、也可以用数字标识符来引用参数值。一些例子:

CREATE FUNCTION sales_tax(REAL) RETURNS REAL AS '
DECLARE
    subtotal ALIAS FOR $1;
BEGIN
    return subtotal * 0.06;
END;
' LANGUAGE 'plpgsql';


CREATE FUNCTION instr(VARCHAR,INTEGER) RETURNS INTEGER AS '
DECLARE
    v_string ALIAS FOR $1;
    index ALIAS FOR $2;
BEGIN
    -- Some computations here
END;
' LANGUAGE 'plpgsql';


CREATE FUNCTION use_many_fields(tablename) RETURNS TEXT AS '
DECLARE
    in_t ALIAS FOR $1;
BEGIN
    RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7;
END;
' LANGUAGE 'plpgsql';

19.3.2. 行类型 #

name tablename%ROWTYPE;

复合类型的变量称为行变量(或 行类型变量)。这样的变量可以保存 SELECT 或 FOR 查询结果的一整行,只要该查询的列集与变量声明的类型相匹配。行值的 各个字段用通常的点表示法访问,例如 rowvar.field。

目前,行变量只能使用 %ROWTYPE 表示法声明;虽然你可能期望直接用表名作为类型声明,但这在 PL/pgSQL 函数中不会被接受。

函数的参数可以是复合类型(完整的表行)。这种情况下,对应的标识符 $n 将是一个行变量,可以从中选择字段,例如 $1.user_id。

行类型变量中只能访问表行的用户定义属性,不能访问 OID 或其他系统 属性(因为该行可能来自视图)。行类型的字段继承表对于 char(n) 等数据类型的字段大小或精度。

CREATE FUNCTION use_two_tables(tablename) RETURNS TEXT AS '
DECLARE
    in_t ALIAS FOR $1;
    use_t table2name%ROWTYPE;
BEGIN
    SELECT * INTO use_t FROM table2name WHERE ... ;
    RETURN in_t.f1 || use_t.f3 || in_t.f5 || use_t.f7;
END;
' LANGUAGE 'plpgsql';

19.3.3. 记录 #

name RECORD;

记录变量类似于行类型变量,但它们没有预定义的结构。它们在 SELECT 或 FOR 命令期间被赋值时,采用被赋行的实际行结构。记录变量的 子结构在每次被赋值时都可以改变。这样做的后果是,记录变量在第一次 被赋值之前没有子结构,任何访问其字段的尝试都会引发 运行时错误。

注意 RECORD 不是真正的数据类型,只是一个占位符。

19.3.4. 属性 #

使用 %TYPE 和 %ROWTYPE 属性,可以声明与另一个数据库项(例如一个表字段)具有相同数据类型 或结构的变量。

variable%TYPE

%TYPE 提供一个变量或数据库列的数据类型。可以用它 来声明将保存数据库值的变量。例如,假设你的 users 表中有一个名为 user_id 的列。 要声明一个与 users.user_id 数据类型相同的 变量,可以这样写:

user_id   users.user_id%TYPE;

使用 %TYPE,你不需要知道所引用结构的数据类型,而且 最重要的是,如果所引用项的数据类型将来发生变化(例如你把 user_id 的表定义从 INTEGER 改为 REAL),可能不需要更改你的函数 定义。

table%ROWTYPE

%ROWTYPE 提供对应于指定表整行的复合数据类型。 table 必须是数据库中现有的表或视图 的名称。

DECLARE
    users_rec users%ROWTYPE;
    user_id users.user_id%TYPE;
BEGIN
    user_id := users_rec.user_id;
    ...

CREATE FUNCTION does_view_exist(INTEGER) RETURNS bool AS '
   DECLARE
        key ALIAS FOR $1;
        table_data cs_materialized_views%ROWTYPE;
   BEGIN
        SELECT INTO table_data * FROM cs_materialized_views
               WHERE sort_key=key;

        IF NOT FOUND THEN
           RETURN false;
        END IF;
        RETURN true;
   END;
' LANGUAGE 'plpgsql';

19.3.5. RENAME #

RENAME oldname TO newname;

使用 RENAME 声明可以更改变量、记录或行的名称。这主要用于在触发器 过程中用另一个名字引用 NEW 或 OLD。另见 ALIAS。

例子:

RENAME id TO user_id;
RENAME this_var TO that_var;

注意

RENAME 在 PostgreSQL 7.3 中似乎是坏的。修复它的优先级很低,因为 ALIAS 已覆盖 RENAME 的大多数实际用途。

提交更正

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