# 43.12.在PL/pgSQL中开发的技巧
在PL/pgSQL中开发的一个好方法是使用您选择的文本编辑器创建函数,并在另一个窗口中使用psql加载和测试这些函数。如果您是这样做的,那么使用创建或替换函数
。这样,您只需重新加载文件即可更新函数定义。例如:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
....
$$ LANGUAGE plpgsql;
在运行psql时,您可以通过以下方式加载或重新加载此类函数定义文件:
\i filename.sql
然后立即发出SQL命令来测试函数。
在PL/pgSQL中开发的另一个好方法是使用GUI数据库访问工具,该工具有助于使用过程语言进行开发。pgAdmin就是这种工具的一个例子,尽管还有其他一些工具。这些工具通常提供方便的功能,例如转义单引号,并使重新创建和调试函数更容易。
# 43.12.1.引号的处理
PL/pgSQL函数的代码在中指定创建函数
作为字符串文本。如果你用普通的方式用单引号写字符串文字,那么函数体中的任何单引号都必须加倍;同样,任何反斜杠都必须加倍(假设使用了转义字符串语法)。双引号充其量是乏味的,在更复杂的情况下,代码可能会变得完全不可理解,因为您很容易发现自己需要六个或更多相邻的引号。建议您将函数体编写为“美元报价”字符串文字(请参见第4.1.2.4节).在美元报价方法中,你永远不会将任何引号加倍,而是要注意为你需要的每一层嵌套选择不同的美元报价分隔符。例如,您可以编写创建函数
命令为:
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_输出
将是:名字像“foobar”和xyz
.
在美元报价法中,你会写道:
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
请注意,任何围绕此的美元报价分隔符都不仅仅是$$
.
6个引号
当函数体中字符串中的单个引号与该字符串常量的结尾相邻时,例如:
a_output := a_output || '' AND name LIKE ''''foobar''''''
附加到的值a_输出
那就是:名字叫“foobar”
.
在美元报价法中,这变成:
a_output := a_output || $$ AND name LIKE 'foobar'$$
10个引号
当你想在一个字符串常量中有两个单引号(占8个引号),而这个单引号与该字符串常量的末尾相邻(另外两个)。您可能只需要在编写生成其他函数的函数时使用它,如例43.10.例如:
a_output := a_output || '' if v_'' ||
referrer_keys.kind || '' like ''''''''''
|| referrer_keys.key_string || ''''''''''
then return '''''' || referrer_keys.referrer_type
|| ''''''; end if;'';
价值a_输出
那就是:
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_输出
,因为它在使用前会被重新引用。
# 43.12.2.额外的编译时和运行时检查
为了帮助用户在简单但常见的问题造成危害之前找到它们的实例,PL/pgSQL提供了额外的*检查
*。启用后,根据配置,它们可用于发出警告
或者错误
在函数的编译过程中。一种接收到警告
可以在不产生进一步消息的情况下执行,因此建议您在单独的开发环境中进行测试。
背景plpgsql。额外警告
或plpgsql。额外错误
,视情况而定“全部”
在开发和/或测试环境中受到鼓励。
这些附加检查通过配置变量启用plpgsql。额外警告
警告和plpgsql。额外错误
因为错误。两者都可以设置为逗号分隔的检查列表,“没有”
或“全部”
.默认值为“没有”
.目前可用的检查清单包括:
阴影_变量
检查声明是否隐藏了以前定义的变量。
严格的多重分配
一些PL/PgSQL命令允许一次为多个变量赋值,例如选择进入
。通常,目标变量的数量和源变量的数量应该匹配,尽管PL/PgSQL将使用无效的
对于缺少的值和额外的变量将被忽略。启用此检查将导致PL/PgSQL抛出警告
或错误
只要目标变量的数量和源变量的数量不同。
太多行了
启用此检查将导致PL/PgSQL检查给定查询在进入
使用子句。作为一个进入
语句将只使用一行,让查询返回多行通常是低效的和/或不确定的,因此可能是错误的。
下面的示例显示了plpgsql。额外警告
开始阴影_变量
:
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
下面的示例显示了设置的效果plpgsql。额外警告
到严格的多重分配
:
SET plpgsql.extra_warnings TO 'strict_multi_assignment';
CREATE OR REPLACE FUNCTION public.foo()
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
x int;
y int;
BEGIN
SELECT 1 INTO x, y;
SELECT 1, 2 INTO x, y;
SELECT 1, 2, 3 INTO x, y;
END;
$$;
SELECT foo();
WARNING: number of source and target fields in assignment does not match
DETAIL: strict_multi_assignment check of extra_warnings is active.
HINT: Make sure the query returns the exact list of columns.
WARNING: number of source and target fields in assignment does not match
DETAIL: strict_multi_assignment check of extra_warnings is active.
HINT: Make sure the query returns the exact list of columns.
foo