pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
块中使用的所有变量都必须在该块的声明区中声明。(唯一的例外是, 在整数值范围上迭代的 FOR 循环的循环变量会被自动声明为 integer 变量。)
PL/pgSQL 变量可以有任何 SQL 数据类型,例如 integer、varchar 和 char。
下面是一些变量声明的例子:
user_id integer; quantity numeric(5); url varchar; myrow tablename%ROWTYPE; myfield tablename.columnname%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;
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;
CREATE FUNCTION concat_selected_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;
当 PL/pgSQL 函数的返回类型声明为多态类型 (anyelement 或 anyarray)时,会创建一个特殊 参数 $0。其数据类型是由实际输入类型推断出的函数 实际返回类型(见 第 33.2.5 节)。这使 函数可以访问自己的实际返回类型,如 第 37.4.2 节 所示。$0 初始 化为空值,可以被函数修改,因此如果愿意,可以用它来保存返回值,尽管 这不是必需的。$0 也可以有别名。例如,下面的函数 适用于任何有 + 操作符的数据类型:
CREATE FUNCTION add_three_values(anyelement, anyelement, anyelement)
RETURNS anyelement AS '
DECLARE
result ALIAS FOR $0;
first ALIAS FOR $1;
second ALIAS FOR $2;
third ALIAS FOR $3;
BEGIN
result := first + second + third;
RETURN result;
END;
' LANGUAGE plpgsql;
variable%TYPE
%TYPE 提供一个变量或表列的数据类型。可以用它来声明 将保存数据库值的变量。例如,假设你的 users 表中有 一个名为 user_id 的列。要声明一个与 users.user_id 数据类型相同的变量,可以这样写:
user_id users.user_id%TYPE;
使用 %TYPE,你不需要知道所引用结构的数据类型,而且 最重要的是,如果所引用项的数据类型将来发生变化(例如你把 user_id 的类型从 integer 改为 real),可能不需要更改你的函数定义。
%TYPE 在多态函数中特别有价值,因为内部变量所需的 数据类型可能随每次调用而变化。把 %TYPE 应用于函数 的参数或结果占位符,即可创建合适的变量。
nametable_name%ROWTYPE;namecomposite_type_name;
复合类型的变量称为行变量(或行类型变量)。 这样的变量可以保存 SELECT 或 FOR 查询结果的 一整行,只要该查询的列集与变量声明的类型相匹配。行值的各个字段用通常 的点表示法访问,例如 rowvar.field。
通过使用 table_name%ROWTYPE 表示法,可以声明一个与现有表或视图的行具有相同类型的行变量;也可以 通过给出复合类型的名称来声明。(由于每个表都有一个同名关联复合类型, 在 PostgreSQL 中写不写 %ROWTYPE 实际上没有区别。但带 %ROWTYPE 的形式可移植性更好。)
函数的参数可以是复合类型(完整的表行)。这种情况下,对应的标识符 $ 将是一个行变量,可以从中选择 字段,例如 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;
name RECORD;
记录变量类似于行类型变量,但它们没有预定义的结构。它们在 SELECT 或 FOR 命令期间被赋值时,采用被赋行的 实际行结构。记录变量的子结构在每次被赋值时都可以改变。这样做的后果 是,记录变量在第一次被赋值之前没有子结构,任何访问其字段的尝试都会 引发运行时错误。
注意 RECORD 不是真正的数据类型,只是一个占位符。还应当 认识到,当 PL/pgSQL 函数声明为返回 record 类型时,这与记录变量并不完全是同一个概念,尽管这样的 函数很可能使用记录变量来保存其结果。两种情况下,编写函数时实际的行 结构都未知,但对于返回 record 的函数,实际结构在解析调用 查询时确定,而记录变量的行结构可以即时改变。
RENAME #RENAMEoldnameTOnewname;
使用 RENAME 声明可以更改变量、记录或行的名称。 这主要用于在触发器过程中用另一个名字引用 NEW 或 OLD。另见 ALIAS。
例子:
RENAME id TO user_id; RENAME this_var TO that_var;
RENAME 在 PostgreSQL 7.3 中似乎是 坏的。修复它的优先级很低,因为 ALIAS 已覆盖 RENAME 的大多数实际用途。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。