PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 40. PL/pgSQL - SQL过程语言 | 下一页

# 40.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，当然还有其它的。这些工具通常提供了一些很有用的功能， 比如转义单引号使得重建和调试函数更简单等。

## 40.11.1. 引号标记处理

PL/pgSQL函数的代码都是在 `CREATE FUNCTION`里以一个字符串文本的方式声明的。 如果你用两边包围单引号的常规方式写字符串文本，那么任何函数体内的单引号都必须写双份； 类似的是反斜杠也必须双份。双份引号非常乏味，在更复杂的场合下，代码可能会让人难以理解， 因为你很容易发现自己需要半打甚至更多相连的引号。 建议你用"dollar-quoted"的字符串文本来写函数体。 (参阅第 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个)。 可能只有在写一个生成其它函数的函数的时候， 像例 40-9里那样。比如：

      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`里放单引号，因为在使用前它会被重新引号包围。

## 40.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

上一页 | 起始页 | 下一页
在后台下的PL/pgSQL | 上一级 | 从Oracle PL/SQL进行移植