↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
历史版本。 PostgreSQL 8.0 已结束支持。 请参阅 当前版本手册.

第 37 章 PL/Perl - Perl 过程语言

PL/Perl 是一种可加载的过程语言,可以用 Perl 编程语言编写 PostgreSQL 函数。

要在某个特定数据库中安装 PL/Perl,使用 createlang plperl dbname。

提示

如果把某种语言安装到template1中,之后创建的所有数据库都会自动安装该语言。

注意

使用源码包的用户必须在安装过程中专门启用 PL/Perl 的构建(更多信息见第 14 章)。使用二进制包的用户可能会在单独的子包中找到 PL/Perl。

37.1. PL/Perl 函数和参数 #

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

CREATE FUNCTION funcname (argument-types) RETURNS return-type AS $$
    # PL/Perl 函数体
$$ LANGUAGE plperl;

函数的主体就是普通的 Perl 代码。

CREATE FUNCTION 命令的语法要求函数体写成一个字符串常量。通常对该字符串常量使用美元引用(见第 4.1.2.2 节)最方便。如果选择使用常规的单引号字符串常量语法,就必须对函数体中用到的单引号(')和反斜线(\)进行转义,通常是把它们写成双份(见第 4.1.2.1 节)。

参数和结果的处理与其他 Perl 子程序一样:参数通过 @_ 传入,结果值通过 return 返回,或者作为函数中最后一个被求值的表达式返回。

例如,一个返回两个整数值中较大值的函数可以定义为:

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
    if ($_[0] > $_[1]) { return $_[0]; }
    return $_[1];
$$ LANGUAGE plperl;

如果一个 SQL 空值被传给一个函数,在 Perl 中该参数值将呈现为“未定义”。上述函数定义对于空值输入的行为并不理想(实际上,它会把它们当作零)。我们可以在函数定义中添加 STRICT,让 PostgreSQL 采取更合理的做法:如果传入空值,函数将根本不会被调用,而是自动返回空值结果。另一种方式是在函数体中检查未定义输入。例如,假设我们希望在 perl_max 的两个参数中一个为空值、另一个非空值时,返回非空值参数而不是空值:

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 函数返回 SQL 空值,就返回一个未定义值。无论函数是否为严格函数,都可以这样做。

复合类型参数被作为哈希的引用传递给函数。哈希的键是复合类型的属性名。这里是一个示例:

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;

PL/Perl 函数也可以用相同的方法返回复合类型:返回一个具有所需属性的哈希的引用。例如:

CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);

CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
    return {f2 => 'hello', f1 => 1, f3 => 'world'};
$$ LANGUAGE plperl;

SELECT * FROM perl_row();

在声明的结果数据类型中,凡是哈希中未出现的列都将作为空值返回。

PL/Perl 函数也可以返回标量类型或复合类型的集合。为此,可以返回一个数组引用,其中对两种情况分别包含标量或哈希引用。下面是几个简单示例:

CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
return [0..$_[0]];
$$ LANGUAGE plperl;

SELECT * FROM perl_set_int(5);


CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
    return [
        { f1 => 1, f2 => 'Hello', f3 => 'World' },
        { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
        { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
    ];
$$  LANGUAGE plperl;

SELECT * FROM perl_set();

注意,采用这种方法时,Perl 必须在内存中构建整个数组;因此该技术无法扩展到非常大的结果集。

PL/Perl 目前对域类型没有完整支持:它把域同其底层标量类型一样对待。这意味着与域关联的约束不会被强制执行。这对函数参数来说不是问题,但如果你把一个 PL/Perl 函数声明为返回域类型,就会存在隐患。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.