PostgreSQL7.0手册-用户手册-10. PL/pgSQL - SQL 过程语言
ow'),所以对于 PL/pgSQL 分析器而言,除了 NULL 关键字以外它是不可能识别真正常量的值的.所有表达式都通过用 SPI 管理器在内部运行查询
SELECT expression
来计算.在表达式里出现的变量标识都被参数和放在参数数组里传入执行器的变量实际值所代替.所有在 PL/pgSQL 函数里用到的表达式都只准备和存储一次.
Postgres 的主分析器做的类型检查对转换常量有一些副作用.详细说来,下面的两个函数有一些区别
CREATE FUNCTION logfunc1 (text) RETURNS datetime AS '
DECLARE
logtxt ALIAS FOR $1;
BEGIN
INSERT INTO logtable VALUES (logtxt, ''now'');
RETURN ''now'';
END;
' LANGUAGE 'plpgsql';
和
CREATE FUNCTION logfunc2 (text) RETURNS datetime AS '
DECLARE
logtxt ALIAS FOR $1;
curtime datetime;
BEGIN
curtime := ''now'';
INSERT INTO logtable VALUES (logtxt, curtime);
RETURN curtime;
END;
' LANGUAGE 'plpgsql';
在 logfunc1() 里,Postgres 的主分析器在准备 INSERT 的规划时认为,字符串 'now' 应该解释为 datetime,因为 logtable 的目标字段是该类型.因此,这时它将从中生成一个常量并且在所有后端生存期内所有对 logfunc1() 的调用时使用该常量.不用说这可不是程序员希望的.
在 logfunc2() 里,Postgres 的主分析器并不知道 'now' 应该转换的类型,因此它返回一个包含字符串 'now' 的 text 数据类型.在给局部变量 curtime 赋值时,PL/pgSQL 解释器通过调用 text_out()和 datetime_in() 把这个字符串转换成 datetime 类型的变量.
这个 Postgres 主分析器的类型检查是在 PL/pgSQL 接近完成的时候实现的.在版本 6.3 和版本 6.4 之间有所不同并且影响所有使用 SPI 管理器的规划特性的函数.使用上面提到的局部变量的方法是目前能让 PL/pgSQL 对那些数值正确解释的唯一方法.
如果在表达式或语句里用到记录(record)字段,字段的数据类型在同一个表达式的不同调用中不应该改变.书写控制多个表的触发器过程时应该注意这一点.
语句
任何象下面声明的 PL/pgSQL 分析器不能理解的东西将被放到查询里并发送给数据库引擎执行.生成的查询应该不返回任何数据.
赋值
给一个变量或行/记录赋值用下面方法
identifier := expression;
如果表达式的结果数据类型和变量数据类型不一致,或者变量具有已知的尺寸/精度(例如 char(20)),结果值将隐含的被 PL/pgSQL 字节码解释器用结果类型的输出函数和变量类型的输入函数转换.要注意这样做可能潜在地导致类型输入函数生成的运行时错误.
下面方法可以把一个完整的选择放到一条记录或者行里
SELECT expressions INTO target FROM ...;
target 可以是一条记录,一行变量或一个逗号分隔的变量列表和记录/行字段(域).
如果一行或者一个变量列表当做目标,选择的数值必须与目标列的结构完全一样,否则会产生一条运行时错误.FORM 关键字可以跟随着任意可在 SELECT 语句里使用的有效的资格(条件),分组,排序等.
一个名为 FOUND 的特殊的布尔类型的变量可以在 SELECT INTO 之后立刻用于检查赋值是否成功.
SELECT * INTO myrec FROM EMP WHERE empname = myname;
IF NOT FOUND THEN
RAISE EXCEPTION ''employee % not found'', myname;
END IF;
如果选择返回多行,只有第一行被放到目标域里面.其他所有都被悄悄地丢弃掉了.
调用其他函数
所有在 Prostgres 数据库里的函数返回一个值.因此,通常的调用函数的方法是执行一条 SELECT 查询或者做一个赋值(导致一个 PL/pgSQL 的内部 SELECT ).但是有时候我们对函数结果并不感兴趣.
PERFORM query
将在 SPI 管理器上执行一个 'SELECT query' 然后丢弃结果.象局部变量这样的标识仍然代入参数.
从函数返回
RETURN expression
函数结束并且表达式 expression 的值将返回给上层执行器.函数的返回值不能取消定义.如果控制到达一个函数体的最顶层而没有碰到一个 RETURN 语句,将产生一个运行时错误.
表达式的结果将被自动转换成函数返回类型--象我们在赋值里描述的那样.
退出和消息
象上面的例子指明的那样,有一个 RAISE 语句可以丢出一条信息到 Postgres elog 机制里面.
RAISE level ''format'' [, identifier [...]];
在格式 ( format )里面,“%” 用做一个后面跟随的逗号分隔的标识的占位符.可能的级别(level)是 DEBUG (安静地停止运行的数据库),NOTICE (向数据库书写日志并向前端客户应用发送信息)和 EXCEPTION (向数据库书写日志并且退出事务 ).
条件
IF expression THEN
statements
[ELSE
statements]
END IF;
表达式 expression 必须返回一个最起码可以转换成布尔类型的数值.
循环
有许多循环的类型.
[<
SELECT expression
来计算.在表达式里出现的变量标识都被参数和放在参数数组里传入执行器的变量实际值所代替.所有在 PL/pgSQL 函数里用到的表达式都只准备和存储一次.
Postgres 的主分析器做的类型检查对转换常量有一些副作用.详细说来,下面的两个函数有一些区别
CREATE FUNCTION logfunc1 (text) RETURNS datetime AS '
DECLARE
logtxt ALIAS FOR $1;
BEGIN
INSERT INTO logtable VALUES (logtxt, ''now'');
RETURN ''now'';
END;
' LANGUAGE 'plpgsql';
和
CREATE FUNCTION logfunc2 (text) RETURNS datetime AS '
DECLARE
logtxt ALIAS FOR $1;
curtime datetime;
BEGIN
curtime := ''now'';
INSERT INTO logtable VALUES (logtxt, curtime);
RETURN curtime;
END;
' LANGUAGE 'plpgsql';
在 logfunc1() 里,Postgres 的主分析器在准备 INSERT 的规划时认为,字符串 'now' 应该解释为 datetime,因为 logtable 的目标字段是该类型.因此,这时它将从中生成一个常量并且在所有后端生存期内所有对 logfunc1() 的调用时使用该常量.不用说这可不是程序员希望的.
在 logfunc2() 里,Postgres 的主分析器并不知道 'now' 应该转换的类型,因此它返回一个包含字符串 'now' 的 text 数据类型.在给局部变量 curtime 赋值时,PL/pgSQL 解释器通过调用 text_out()和 datetime_in() 把这个字符串转换成 datetime 类型的变量.
这个 Postgres 主分析器的类型检查是在 PL/pgSQL 接近完成的时候实现的.在版本 6.3 和版本 6.4 之间有所不同并且影响所有使用 SPI 管理器的规划特性的函数.使用上面提到的局部变量的方法是目前能让 PL/pgSQL 对那些数值正确解释的唯一方法.
如果在表达式或语句里用到记录(record)字段,字段的数据类型在同一个表达式的不同调用中不应该改变.书写控制多个表的触发器过程时应该注意这一点.
语句
任何象下面声明的 PL/pgSQL 分析器不能理解的东西将被放到查询里并发送给数据库引擎执行.生成的查询应该不返回任何数据.
赋值
给一个变量或行/记录赋值用下面方法
identifier := expression;
如果表达式的结果数据类型和变量数据类型不一致,或者变量具有已知的尺寸/精度(例如 char(20)),结果值将隐含的被 PL/pgSQL 字节码解释器用结果类型的输出函数和变量类型的输入函数转换.要注意这样做可能潜在地导致类型输入函数生成的运行时错误.
下面方法可以把一个完整的选择放到一条记录或者行里
SELECT expressions INTO target FROM ...;
target 可以是一条记录,一行变量或一个逗号分隔的变量列表和记录/行字段(域).
如果一行或者一个变量列表当做目标,选择的数值必须与目标列的结构完全一样,否则会产生一条运行时错误.FORM 关键字可以跟随着任意可在 SELECT 语句里使用的有效的资格(条件),分组,排序等.
一个名为 FOUND 的特殊的布尔类型的变量可以在 SELECT INTO 之后立刻用于检查赋值是否成功.
SELECT * INTO myrec FROM EMP WHERE empname = myname;
IF NOT FOUND THEN
RAISE EXCEPTION ''employee % not found'', myname;
END IF;
如果选择返回多行,只有第一行被放到目标域里面.其他所有都被悄悄地丢弃掉了.
调用其他函数
所有在 Prostgres 数据库里的函数返回一个值.因此,通常的调用函数的方法是执行一条 SELECT 查询或者做一个赋值(导致一个 PL/pgSQL 的内部 SELECT ).但是有时候我们对函数结果并不感兴趣.
PERFORM query
将在 SPI 管理器上执行一个 'SELECT query' 然后丢弃结果.象局部变量这样的标识仍然代入参数.
从函数返回
RETURN expression
函数结束并且表达式 expression 的值将返回给上层执行器.函数的返回值不能取消定义.如果控制到达一个函数体的最顶层而没有碰到一个 RETURN 语句,将产生一个运行时错误.
表达式的结果将被自动转换成函数返回类型--象我们在赋值里描述的那样.
退出和消息
象上面的例子指明的那样,有一个 RAISE 语句可以丢出一条信息到 Postgres elog 机制里面.
RAISE level ''format'' [, identifier [...]];
在格式 ( format )里面,“%” 用做一个后面跟随的逗号分隔的标识的占位符.可能的级别(level)是 DEBUG (安静地停止运行的数据库),NOTICE (向数据库书写日志并向前端客户应用发送信息)和 EXCEPTION (向数据库书写日志并且退出事务 ).
条件
IF expression THEN
statements
[ELSE
statements]
END IF;
表达式 expression 必须返回一个最起码可以转换成布尔类型的数值.
循环
有许多循环的类型.
[<

