您的位置:寻梦网首页编程乐园数据库PostgreSQL 7.2 Documentation

25.3. 描述

25.3.1. PL/Perl 函数和参数

要用 PL/Perl 语言创建一个函数,可以使用标准的语法

CREATE FUNCTION 

funcname

 (

argument-types

) RETURNS 

return-type

 AS '
    # 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 中 "undefined" 的形式出现.上面的函数定义对 NULL 输入将处理得非常好(实际上, 它将表现得好像它们都是零一样).我们可以给函数定义增加 WITH (isStrict) ,让 PostgreSQL 做一些更合理的事情∶如果传递进来一个 NULL,那么该函数则根本不会被 调用,而只是自动返回一个 NULL.另外,我们可以在函数体里检查 未定义(undefined)的输入.比如,假设我们想收到一个 null 和一个非 null 参数的 perl_max 返回非 null 的参数,而不是 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,我们可以返回一个 未定义(undef)的数值.不管该函数是否严格,我们都可以这么做.

复合类型的参数是当做指向散列的引用传递给函数的. 散列的键字是复合类型的属性名.下面是一个例子∶

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 语言创建, 那么执行就会成功.

25.3.2. PL/Perl 里的数据值

给 PL/Perl 函数的脚本提供的参数值都只是转换成文本形式 的输入参数(就象它们在 SELECT 语句中显示出来的那样). 相反, return 命令会接受任何该函数声明的返回类型 可以接受的输入格式.因此,PL/Perl 程序员可以把数据值当做 文本来操作.

25.3.3. 在 PL/Perl 里访问数据库

从你的 Perl 函数内部访问数据库本身可以通过一个 试验模块 DBD::PgSPI 完成(也可以在 CPAN 镜像站 获得.)这个模块可以给我们一个兼容 DBI 的数据库 句柄,叫做 $pg_dbh ,你可以用它用普通的 DBI 语法执行查询.

PL/Perl 本身目前只提供一个额外的 Perl 命令∶

elog level , msg

发出一个日志或者错误信息.可能的级别是 DEBUG NOTICE ,和 ERROR DEBUG NOTICE 只是将给定的信息发送到 postmaster 日志(并且在 NOTICE 的情况下还发送发送给客户端). ERROR 抛出一个错误条件∶函数其它的部分将被废弃, 当前的事务将退出.

25.3.4. 缺失的特性

PL/Perl 函数不能直接相互调用(因为它们在 Perl 内部是匿名子过程). 目前它们之间也没有办法共享全局变量.

目前我们不能用 PL/Perl 写触发器函数.

应该把 DBD::PgSPI 或者类似的功能集成到标准的 PostgreSQL 版本中.