用 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 工具。比如 PgAccess ,当然还有其它的。这些工具通常提供了一些很有用的功能,比如逃逸单引号使得重建和调试函数更简单等。
PL/pgSQL 函数的代码都是在 CREATE FUNCTION 里以一个字符串文本的方式声明的。如果你用两边包围单引号的常规方式写字符串文本,那么任何函数体内的单引号都必须写双份;类似的是反斜杠也必须双份。双份引号非常乏味,在更复杂的场合下,代码可能会让人难以理解,因为你很容易发现自己需要半打甚至更多相连的引号。建议你用"美元符界定"的字符串文本来写函数体。(参阅节4.1.2.2)。使用美元符界定的时候,你从不需要对任何引号写双份,只需要为每层引号包围嵌套选择一个不同的美元符号包围分隔符即可。比如,你可能这么写 CREATE FUNCTION 命令
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$ .... $PROC$ LANGUAGE plpgsql;
在这个函数体中,可以在 SQL 命令里使用单引号包围文本字符串,用 $$ 分隔那些 SQL 命令的片断。如果你需要对包含 $$ 的文本进行引号包围,可以使用 $Q$ 等等。
下表展示了不使用美元符界定的时候该如何写单引号。把美元符引号之前的引号包围的代码转换成某种可以理解的形式时,应该会用得上。
开始/结束函数体,比如:
CREATE FUNCTION foo() RETURNS integer AS ' .... ' LANGUAGE plpgsql;
在函数体内部的任何位置,问号都必须成对出现。
对于函数体内的字符串文本,比如:
a_output := ''Blah''; SELECT * FROM users WHERE f_name=''foobar'';
在美元符界定的方法里,你只要写
a_output := 'Blah'; SELECT * FROM users WHERE f_name='foobar';
两种情况都是 PL/pgSQL 分析器期望看到的东西。
如果你在函数体中的字符串里面需要一个单引号,比如:
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$$
注意,这样的美元符界定的分隔符并不是只有 $$
如果一个在函数体中的字符串内的单引号与该字符串常量结尾前后相连,比如:
a_output := a_output || '' AND name LIKE ''''foobar''''''
a_output 的值将是 AND name LIKE 'foobar'
用美元符界定的方法则为是
a_output := a_output || $$ AND name LIKE 'foobar'$$
如果你想要在字符串常量里有两个单引号(它们在一起是 8 个了),并且这两个单引号和该字符串常量的结尾相连(又加 2 个)。可能只有在写一个生成其它函数的函数的时候,像例37-6里那样,才需要这么干。比如:
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 里放单引号,因为在使用前它会被重新引号包围。