pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
要用 PL/Perl 语言创建函数,使用标准的语法
CREATE FUNCTIONfuncname(argument-types) RETURNSreturn-typeAS ' # PL/Perl function body ' LANGUAGE plperl;
PL/PerlU 与此相同,只是语言应指定为 plperlu。
函数体是普通的 Perl 代码。参数和 结果的处理与任何其他 Perl 子例程一样:参数 通过 @_ 传入,结果值 用 return 或作为函数中最后求值的 表达式返回。例如,一个返回两个整数值中 较大者的函数可以这样定义:
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS '
if ($_[0] > $_[1]) { return $_[0]; }
return $_[1];
' LANGUAGE plperl;
如果把一个 NULL 传给函数,参数值在 Perl 中将显示为 “未定义”。上面的函数定义对 NULL 输入表现不太好 (事实上,它会把它们当作零来处理)。我们可以在 函数定义中加上 WITH (isStrict), 让 PostgreSQL 做更合理的事情:如果传入 NULL,函数根本不会被调用, 而是自动返回 NULL 结果。另一种做法是在函数体内检查未定义的 输入。例如,假设我们希望 perl_max 在一个参数为空、另一个非空时 返回非空的那个参数, 而不是返回 NULL:
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS '
my ($a,$b) = @_;
if (! defined $a) {
if (! defined $b) { return undef; }
return $b;
}
if (! defined $b) { return $a; }
if ($a > $b) { return $a; }
return $b;
' LANGUAGE plperl;
如上所示, 要让 PL/Perl 函数返回 NULL, 就返回一个未定义的值。无论函数 是否为 strict,都可以 这样做。
复合类型的参数以哈希的引用形式 传给函数。哈希的键是该复合类型的 属性名。下面是一个例子:
CREATE TABLE employee (
name text,
basesalary integer,
bonus integer
);
CREATE FUNCTION empcomp(employee) RETURNS integer AS '
my ($emp) = @_;
return $emp->{''basesalary''} + $emp->{''bonus''};
' LANGUAGE plperl;
SELECT name, empcomp(employee) FROM employee;
目前不支持返回复合类型的 结果值。
由于函数体是作为 SQL 字符串字面量 传给 CREATE FUNCTION 的,你必须 转义 Perl 源码中的单 引号和反斜线,通常像 上例那样将它们加倍。另一种 可行的方法是使用 Perl 的 扩展引号函数( q[]、qq[]、 qw[])来避免写单引号。
下面是一个由于安全原因不允许文件系统 操作而不能工作的函数例子:
CREATE FUNCTION badfunc() RETURNS integer AS '
open(TEMP, ">/tmp/badfile");
print TEMP "Gotcha!\n";
return 1;
' LANGUAGE plperl;
这个函数的创建会成功,但执行它不会成功。
注意,如果同一个函数是由超级用户用语言 plperlu 创建的,执行就会 成功。
提供给 PL/Perl 函数脚本的参数值只是 转换为文本形式的输入参数 (就像它们被 SELECT 语句显示出来一样)。反过来,return 命令接受任何作为函数声明的返回 类型可接受输入格式的 字符串。因此,PL/Perl 程序员可以像操作 纯文本一样操作数据值。
从 Perl 函数访问数据库本身可以通过 实验性模块 DBD::PgSPI (也可在 CPAN 镜像站点获取)完成。该模块提供了一个名为 $pg_dbh 的 符合 DBI 的数据库 句柄,可以用 正常的 DBI 语法执行 查询。
PL/Perl 本身目前只提供一个额外的 Perl 命令:
elog level, msg发出一条日志或错误消息。可能的级别有 DEBUG、 NOTICE 和 ERROR。 DEBUG 和 NOTICE 只是把给定的消息发送到 postmaster 日志(对 NOTICE 而言还会发送给 客户端)。ERROR 引发一个 错误条件:函数 的进一步执行被放弃,当前 事务被中止。
PL/Perl 函数不能直接相互 调用(因为它们是 Perl 内部的 匿名子例程)。目前也没有 办法让它们共享 全局变量。
PL/Perl 目前不能用于编写 触发器函数。
DBD::PgSPI 或类似的能力应当被 集成进标准 PostgreSQL 发行版。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。