pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
块中使用的所有变量、行和记录都必须在块的声明部分中声明。 (唯一的例外是遍历一段整数取值范围的 FOR 循环的循环变量, 它会被自动声明为整数变量。)
PL/pgSQL变量可以有任何 SQL 数据类型,例如 INTEGER、VARCHAR和 CHAR。
下面是一些变量声明的例子:
user_id INTEGER; quantity NUMERIC(5); url VARCHAR;
变量声明的一般语法是:
name[ CONSTANT ]type[ NOT NULL ] [ { DEFAULT | := }expression];
DEFAULT 子句(如果给出)指定进入块时赋给变量的初始值。 如果没有给出 DEFAULT 子句,那么变量会被初始化为 SQL的 NULL 值。
CONSTANT 选项防止变量被赋值,从而让它的值在块的整个 期间保持常量。如果指定了 NOT NULL,赋予 NULL 值会导致 一个运行时错误。所有声明为 NOT NULL 的变量都必须指定 一个非 NULL 的默认值。
默认值在每次进入块时都会被求值。因此举例来说,把 'now'赋给一个timestamp类型的 变量会让该变量拥有当前这次函数调用的时间,而不是函数被 预编译时的时间。
例子:
quantity INTEGER DEFAULT 32; url varchar := ''http://mysite.com''; user_id CONSTANT INTEGER := 10;
nameALIAS 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';
nametablename%ROWTYPE;
复合类型的变量被称为行变量(或 行类型变量)。这样的变量可以保存 SELECT 或 FOR 查询结果的一整行,只要该查询的列集合与变量 声明的类型相匹配。行值的各个字段使用通常的点号记法访问, 例如rowvar.field。
目前,行变量只能用%ROWTYPE记法声明;虽然 人们可能期望裸表名也能用作类型声明,但在 PL/pgSQL函数中它不会被接受。
函数的参数可以是复合类型(完整的表行)。这种情况下,对应的 标识符 $n 将是一个行变量,可以从中选取字段,例如 $1.user_id。
行类型变量只能访问表行的用户定义属性,而不能访问 OID 或 其他系统属性(因为该行可能来自一个视图)。行类型的字段 继承表中该字段的尺寸或精度(对于char(n)这样的 数据类型)。
name RECORD;
记录变量与行类型变量类似,但它们没有预定义的结构。它们会 采用在 SELECT 或 FOR 命令期间赋给它们的行的实际行结构。 记录变量的子结构在每次被赋值时都可能改变。这带来的一个 后果是:在记录变量第一次被赋值之前,它没有 子结构,任何访问其中字段的尝试都会引发运行时错误。
注意RECORD不是真正的数据类型,只是一个占位符。 因此举例来说,你不能声明一个返回RECORD 的函数。
使用%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';
RENAMEoldnameTOnewname;
使用 RENAME 声明可以更改变量、记录或行的名字。这主要在 需要在触发器过程内部用另一个名字引用 NEW 或 OLD 时有用。 另见 ALIAS。
例子:
RENAME id TO user_id; RENAME this_var TO that_var;
截至 PostgreSQL 7.2,RENAME 似乎已损坏。修复它的优先级较低, 因为 ALIAS 覆盖了 RENAME 的大部分实际用途。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。