选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

42.11. PL/pgSQL开发提示 #

PL/pgSQL中进行开发的一种好方法,是用你喜欢的文本编辑器编写函数,并在另一个窗口里使用psql载入和测试这些函数。如果你采用这种方式,最好使用CREATE OR REPLACE FUNCTION来编写函数。这样只需重新载入该文件,就可以更新函数定义。例如:

CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
          ....
$$ LANGUAGE plpgsql;

在运行psql期间,你可以用下面的命令载入或者重载这样一个函数定义文件:

\i filename.sql

并且接着立即发出 SQL 命令来测试该函数。

另一种开发PL/pgSQL的好方法,是使用有助于过程语言开发的 GUI 数据库访问工具。这类工具的一个例子是pgAdmin,当然也有其他工具。它们通常提供一些方便的特性,例如转义单引号,以及让重新创建和调试函数变得更容易。

42.11.1. 引号的处理 #

一个PL/pgSQL函数的代码在一个CREATE FUNCTION中被指定为一个字符串。如果你用通常的方式把该字符串写在单引号中间,那么该函数体中的任何单引号都必须被双写;同样任何反斜线也必须被双写(假定使用了转义字符串语法)。双写引号最多有点冗长,并且在更复杂的情况中代码会变得完全无法理解,因为你很容易发现你需要半打或者更多相邻的引号。我们推荐你转而把函数体写成一个美元引用的字符串(见Section 4.1.2.4)。在美元引用方法中,你从不需要双写任何引号。但是要注意为你需要的每一层嵌套选择一个不同的美元引用定界符。例如,你可能把CREATE FUNCTION命令写成:

CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$
          ....
$PROC$ LANGUAGE plpgsql;

在这里面,你可以在 SQL 命令中为简单字符串使用引号并且用$$来界定被你组装成字符串的 SQL 命令片段。如果你需要引用包括$$的文本,你可以使用$Q$等等。

下表展示了在不使用美元引用时,编写引号必须采取的做法。在把旧式的非美元引用代码改写成更易理解的形式时,它可能会有所帮助。

1 个引号

用来开始和结束函数体,例如:

CREATE FUNCTION foo() RETURNS integer AS '
          ....
' LANGUAGE plpgsql;

在一个单引号引用的函数体中的任何位置,引号必须成对出现。

2 个引号

用于函数体内的字符串,例如:

a_output := ''Blah'';
SELECT * FROM users WHERE f_name=''foobar'';

在美元引用方法中,你只需要写:

a_output := 'Blah';
SELECT * FROM users WHERE f_name='foobar';

这恰好就是PL/pgSQL在两种情况中会看到的。

4 个引号

当你在函数内的一个字符串常量中需要一个单引号时,例如:

a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''

实际会被追加到a_output的值将是: AND name LIKE 'foobar' AND xyz

在美元引用方法中,你可以写:

a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$

要小心在这周围的任何美元引用定界符不只是$$

6 个引号

当在函数体内的一个字符串中的一个单引号与该字符串常量末尾相邻,例如:

a_output := a_output || '' AND name LIKE ''''foobar''''''

被追加到a_output的值则将是: AND name LIKE 'foobar'

在美元引用方法中,这会变成:

a_output := a_output || $$ AND name LIKE 'foobar'$$
10 个引号

当你想在一个字符串常量(占 8 个引号)中有两个单引号时并且这会挨着该字符串常量的末尾(另外 2 个)。如果你正在写一个产生其他函数的函数(如Example 42.10中),你将很可能只需要这种。例如:

a_output := a_output || '' if v_'' ||
    referrer_keys.kind || '' like ''''''''''
    || referrer_keys.key_string || ''''''''''
    then return ''''''  || referrer_keys.referrer_type
    || ''''''; end if;'';

a_output的值将是:

if v_... like ''...'' then return ''...''; end if;

在美元引用方法中,这会变成:

a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
    || referrer_keys.key_string || $$'
    then return '$$  || referrer_keys.referrer_type
    || $$'; end if;$$;

这里我们假定我们只需要把单引号放在a_output中,因为在使用前它将被再引用。

42.11.2. 额外的编译时检查 #

为了辅助用户在一些简单但常见的问题产生危害之前找到它们, PL/pgSQL提供了额外的检查。当被启用时, 根据配置,它们可以在一个函数的编译期间被用来发出 WARNING或者ERROR。一个已经收到了 WARNING的函数可以被继续执行而不会产生进一步的消息, 因此建议你在一个单独的开发环境中进行测试。

这些额外检查通过配置变量启用,其中plpgsql.extra_warnings用于警告,plpgsql.extra_errors用于错误。两者都可以设为逗号分隔的检查项列表、"none""all"。默认值为"none"。当前可用的检查只有一项:

shadowed_variables

检查声明是否遮蔽了先前定义的变量。

下面的例子展示了此设置的效果:plpgsql.extra_warnings设为shadowed_variables

SET plpgsql.extra_warnings TO 'shadowed_variables';

CREATE FUNCTION foo(f1 int) RETURNS int AS $$
DECLARE
f1 int;
BEGIN
RETURN f1;
END;
$$ LANGUAGE plpgsql;
WARNING:  variable "f1" shadows a previously defined variable
LINE 3: f1 int;
        ^
CREATE FUNCTION