最近在研究postgresql,因此也就对PL/pgsql产生了浓厚的兴趣,因此这里就来稍微的总结一下,首先说一下的是这个PL是Procedure Language的简写,也就是所谓的"过程语言“。 下面的很大一部分内容都是引用自pgsql手册,但是也根据自己的理解进行了一些简单的改变。
第一,调用时机
其中PL/pgsql的函数被第一次调用的时候,其函数内的源代码会被解析为二进制指令树,但是对于函数内的表达式还有一些指令,只有在被首次使用的时候,pgsql才会给它制定执行计划,而且这个执行计划会在本次的session中被反复使用。一般来说,这么做是合理的,通常一个session中的使用情景都是差不多的。
但是这么做可能会产生问题,那就是如果我们动态的修改了相应的数据库对象,就有可能会产生问题。而且需要注意的是,如果在一个条件语句中,有部分sql命令或者表达式没有被使用到,那么plpgsql解释器在本次调用中将不会为其准备执行计划。
第二,函数创建语法
下面是我们通常创建一个函数的格式:
CREATE FUNCTION populate() RETURNS integer AS $$
DECLARE
-----声明若干变量
BEGIN
PERFORM my_function();
END;
$$ LANGUAGE plpgsql;
在上面的格式中,其中PERFORM语句的执行计划将会引用my_function对象的oid。如果在这之后,如果我们重建了my_function()函数,那么populate函数将无法找到原有my_function函数的oid。
为了解决这类问题,我们可以选择重建populated函数,或者建立一个新的会话,从而让pgsql来重新编译该函数。通常我们在创建一个函数的时候使用CREATE OR REPLACE FUNCTION命令。
因此我们在plpgsql中直接出现的sql命令再每次执行的时候必须使用相同的表和字段,也就是说,我们不能将函数的参数用作sql命令的表名或者字段名。如果我们想绕开这个限制,我们可以使用plpgsql中的execute语句来动态的构建命令,它会导致的问题就是每次执行的时候都需要构造一个新的命令计划。
使用plpgsql函数的一个非常重要的优势就是可以提高程序的执行效率,因为原有的sql调用需要在客户端与服务器之间反复传递数据,这样不仅增加了进程间通讯所产生的开销,而且也会加大网络IO的开销。
第三,基本结构
由于plpgsql是一种块结构语言,因此函数定义的所有文本都必须写到一个块中,其中块内的每个声明和每条语句都必须以分号结束。块之间是可以嵌套的,而且子块的END关键字后面必须用分号结束,不过对于函数体的最后一个END关键字,分号可以省略。
下面是一个常见的格式范例:
[ << label >> ]
[DECLARE 变量声明]
BEGIN
其他语句;
END [label];
其中在plpgsql中,有两种注释风格,其中双破折号也就是--表示单行注释,而/* */则是多行注释,这里借鉴了C语言中的多行注释风格。
需要注意的是,在语句块前面的声明段中定义的变量在每次进入语句块时都会将声明的变量初始化为缺省值,而不是每次函数调用时初始化一次。