http://man.chinaunix.net/database/postgresql_8.0_CN/plpgsql-declarations.html
创建plpgsql语言
create language plpgsql;
例子一
CREATE OR REPLACE FUNCTION instr(character varying, integer)
RETURNS integer AS
$BODY$
declare
str alias for $1;
ind alias for $2;
begin
return ind+100;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
> select instr('aaa',100) ;
> 200
例子二
如果一个 PL/pgSQL 函数的返回类型声明为一个多态类型 (anyelement 或者 anyarray),那么就会创建一个特殊的参数, $0。它的数据类型是函数的实际返回类型,和从实际输入类型推导推导类型一样 (参阅 Section 31.2.5)。 这样就允许函数访问它的实际返回类型,像 Section 35.4.2 里显示的那样。 $0 初始化为空,并且可以被函数修改,所以,如果需要,它可以用于保存返回值, 虽然这并非必须的。$0 还可以给予一个别名。比如,这个函数可以在任何有 + 操作符的数据类型上运转:
create or replace function addT (v1 anyelement, v2 anyelement, v3 anyelement)
returns anyelement as $$
declare
res alias for $0;
begin
res := v1+v2+v3;
return res;
end;
$$language plpgsql;
> select addT(100,200,300)
> 600
例子三
variable%TYPE
%TYPE 提供一个变量或者表字段的数据类型。 你可以用这个声明将要保存数据库数值的变量。比如,假如你在 users 表里面有一个字段叫 user_id。要声明一个和 users.user_id 类型相同的变量,你可以写:
user_id users.user_id%TYPE;
通过使用 %TYPE,你必须知道你引用的结构的数据类型, 并且,最重要的是,如果被引用项的数据类型在将来变化了(比如:你把 user_id 的类型从 integer 改成 real),你也不需要修改你的函数定义。
%TYPE 对多态的函数特别有用,因为内部变量的数据类型可能在不同调用中是不一样的。 我们可以通过给函数的参数或者结果占位符附加 %TYPE 的方法来创建合适的变量。
例子四
行类型
name table_name%ROWTYPE;
name composite_type_name;
一个复合类型变量叫做行变量(或者row-type变量)。 这样的一个变量可以保存一次SELECT或者 FOR命令结果的完整一行,只要命令的字段集匹配该变量声明的类型。 行数值的独立的字段是使用常用的点表示法访问的,比如 rowvar.field。
一个行变量可以声明为和一个现有的表或者视图的行类型相同,方法是使用 table_name%ROWTYPE 表示法; 或者你也可以声明它的类型是一个复合类型的名字。(因为每个表都有一个相关联的同名数据类型, 在 PostgreSQL 里实在是无所谓你写不写 %ROWTYPE。但是有 %ROWTYPE 的形式移植性更好。)
函数的参数可以是复合类型(表的完整行)。这个时候, 对应的标识符 $n 将是一个行变量,并且可以从中选取字段,比如 $1.user_id。
在一个行类型的变量中,只可以访问用户定义的表中行的属性, 不包括 OID 或者其他系统属性(因为该行可能来自一个视图)。 该行类型的数据域继承表中象 char(n) 这种类型字段的尺寸和精度。
这里是一个使用复合类型的例子:
CREATE TABLE tbl_store1
(
store_no integer NOT NULL DEFAULT nextval('tbl_store1_sq'::regclass),
parent_id integer,
"type" integer,
"values" real,
CONSTRAINT tbl_store1_pkey PRIMARY KEY (store_no)
)
插入植 1 1 1 1;
CREATE OR REPLACE FUNCTION merge(t_row tbl_store1)
RETURNS text AS
$BODY$
declare
t2_row tbl_store1%rowtype;
begin
select * into t2_row from tbl_store1 ;
return t_row.values || t2_row.values;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
> select merge(t.*) from tbl_store1 t ;
> 11
例子五
/**
create or replace function logfun1(log text) returns timestamp as $$
begin
insert into tbl_store1 values(3,1,1,1,'now');
return 'now';
end;
$$ language plpgsql;
select logfun1('test');
**/
create or replace function logfun2(log text) returns timestamp as $$
declare
ctime timestamp;
begin
ctime :='now';
insert into tbl_store1 values(6,2,1,1,ctime);
return ctime;
end;
$$ language plpgsql;
select logfun2('aaa');
在 logfunc1() 的实例里, PostgreSQL 的主分析器在为 INSERT 准备执行计划的时候知道字串 'now' 应该解释成 timestamp 类型,因为 logtable 的目标字段就是该类型。所以,它会在这个时候从这个字串中计算一个常量, 然后在该服务器的整个生存期中的所有 logfunc1 调用中使用这个常量。不消说,这可不是程序员想要的。
在logfunc2里, PostgreSQL 的主分析器并不知道 now 应该转换成什么类型, 因此它返回一个包含字符串 now 的类型为 text 的数据值。 在随后给局部变量curtime赋值时, PL/pgSQL解释器通过调用 text_out和timestamp_in 把这个字符串转换成 timestamp 类型的变量。 因此,计算出的时戳就会按照程序员希望的那样在每次执行的时候都更新。
记录变量的易变性天性在这种结合上提出了一个问题。 在一个记录变量在语句或者表达式中使用时, 该字段的数据类型在同一个表达式的不同调用期间不能修改, 因为该表达式准备使用的是运行第一次到达该表达式时出现的数据类型。 在写处理超过一个表的事件的触发器过程的时候一定要把这个记住。(必要时可以用EXECUTE绕开这个问题。)
例子六
create or replace function tSInto () returns varchar as
$$
declare rec record;
begin
select into rec * from tbl_store1 where values =1;
if not found then
return 'test';
else
return 'tttt';
end if;
end;
$$
language plpgsql;
select tSInto();
create or replace function tSInto () returns varchar as
$$
declare rec record;
begin
select into rec * from tbl_store1 where values =1;
if rec.values isNULL then
return 'okkkkkkk';
else return 'test';
end if ;
end;
$$
language plpgsql;
select tSInto();
例子七
create or replace function cur1 () returns text as
$$
declare
curs1 CURSOR for select * from tbl_store1;
res text :='';
a varchar;
b varchar;
c varchar;
d varchar;
e varchar;
begin
OPEN curs1;
loop
fetch curs1 into a,b,c,d,e;
if not found then
return 'error';
exit;
end if;
res = 'test'||res;
end loop;
close curs1;
return res;
end;
$$
language plpgsql;
CREATE OR REPLACE FUNCTION cur1()
RETURNS text AS
$BODY$
declare
curs1 CURSOR for select * from tbl_store1;
res text :='';
a varchar;
b varchar;
c varchar;
d varchar;
e varchar;
begin
OPEN curs1;
loop
fetch curs1 into a,b,c,d,e;
if (found) then
if (a is null) then
a = '';
end if ;
if (b is null) then
b = '';
end if ;
if (c is null) then
c = '';
end if ;
if (d is null) then
d = '';
end if ;
if (e is null) then
e = '';
end if ;
res = res || a || b || c || d || e;
else
exit;
end if;
end loop;
close curs1;
return res;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
select cur1();
</script>