赞
踩
目录
IF ... THEN ... ELSE ... END IF
IF ... THEN ... ELSEIF ... THEN ... ELSE ... END IF
CASE ... WHEN ... THEN ... ELSE ... END CASE
CASE WHEN ... THEN ... ELSE ... END CASE
两个命令让我们可以从函数中返回数据:return 和 return next。
语法:RETURN expression;
表达式RETURN用于终止函数并把expression的值返回给调用者。这种形式用于不返回集合数据(数据集)的PL/pgSQL函数。
用法详解
(1)如果函数返回一个标量类型,表达式结果将自动转行成函数的返回类型。但要返回一个复合(行)值,必须写一个所需列集合的表达式。
标量示例
create or replace function fn_scalar() returns numeric as
$$
declare
begin
return (3+4*2)-(2*2-1);
end
$$
language plpgsql
复合示例
create or replace function fn_scalars() returns record as
$$
declare
begin
return (1,2,'three'::text);
end
$$
language plpgsql
select * from fn_scalars() as (first int, second int,third text);
--函数中使用record类型来接受,调用时需要构造正确类型。或者函数中构造正确类型返回,然后直接select * from 调用。
(2)如果声明带输出参数的函数,只需要写不带表达式的RETURN,输出参数变量的当前值被返回
create or replace function fn_out_return(out rcd text) returns text as
$$
declare
begin
select name into rcd from t_test where id =3;
return ; --有out参数这个return也可以省略。
end
$$
language plpgsql
(3)如果声明函数返回void,RETURN可以用来提前结果函数,但函数最后不要写RETURN
create or replace function fn_void_return() returns void as
$$
begin
raise notice '执行第一行';
raise notice '执行第二行';
return;
raise notice '执行第三行';
end
$$
language plpgsql
调用函数:可以看到执行完第二行函数直接return返回结束了。
语法: RETURN NEXT expression;
RETURN QUERY query;
RETURN QUERY EXECUTE command-string [ USING expression [,...]];
当函数被声明为返回returns setof sometype,规则和直接return sometype有所不同。这种情况下,返回的个体项被RETURN NEXT或者RETURN QUERY 命令序列指定,并接着会用一个不带参数的RETURN命令来指示这个函数已经完成执行。
(1)RETURN NEXT可以返回标量和复合类型,对于复合类型,将返回一个完整的结果“表”(结果集)。
create or replace function fn_return_nexts() returns setof t_test as
$$
declare
r t_test%rowtype;
begin
for r in select * from t_test
loop
--这里可以对每一行数据进行操作
raise notice 'user_name=%',r.name;
return next r; --返回SELECT的当前行
end loop;
return; --表明函数执行完毕
end
$$
language plpgsql
(2)RETURN QUERY 将执行一个查询的结果追加到一个函数结果中。
create or replace function fn_return_query() returns setof t_test as
$$
declare
r record;
begin
return query(select * from t_test);
end
$$
language plpgsql
RETURN NEXT和RETURN QUERY实际上不会从函数返回:它简单地想函数结果集中追加零或多行,然后继续执行下一条语句,以此建立一个结果集,最后一个RETURN(无参数)控制退出函数。
(3)RETURN QUERY EXECUTE是RETURN QUERY的一个变体,主要用来执行动态查询。可以通过USING想计算出的查询字符串中插入参数表达式,这与在EXECUTE中使用方法一致。
参考的例子,我们往子表t_user_12中多添加几行数据
insert into t_user(name,age,code) values('赵六',20,'12011-11');
insert into t_user(name,age,code) values('刘七',21,'12012-11');
create or replace function fn_query_execute(partition_code varchar)
returns setof t_user as
$$
declare
var_sql text;
begin
var_sql := 'select * from t_user_'||partition_code||';';
raise notice '====%',var_sql;
return query EXECUTE var_sql;
end
$$
language plpgsql
调用函数:
目前plpgsql支持三种IF条件控制语法:
IF ... THEN ... END IF
IF ... THEN ... ELSE ... END IF
IF ... THEN ... ELSEIF ... THEN ... ELSE ... END IF
以及两种CASE语法:
CASE ... WHEN ... THEN ... ELSE ... END CASE
CASE WHEN ... THEN ... ELSE ... END
例子:
create or replace function fn_if_then(uid boolean) returns text as
$$
declare
v_value text default '参数值不为TRUE';
begin
if uid = true then
v_value='参数值为TRUE';
end if;
return v_value;
end
$$
language plpgsql
调用函数:
例子:
create or replace function fn_if_else(uid int) returns text as
$$
declare
v_value text;
begin
if uid = 1 then
v_value='参数值为1';
else
v_value='参数值不为1';
end if;
return v_value;
end
$$
language plpgsql
调用函数:
例子:
create or replace function fn_if_elseif(uid int) returns text as
$$
declare
v_value text;
begin
if uid = 1 then
v_value='参数值为1';
elseif uid=2 then
v_value='参数值为2';
else
v_value='参数值即不为1也不为2';
end if;
return v_value;
end
$$
language plpgsql
调用函数:
例子:
create or replace function fn_if_elseifs(uid int) returns text as
$$
declare
v_value text;
begin
if uid = 1 then
v_value='参数值为1';
elseif uid=2 then
v_value='参数值为2';
elseif uid=3 then
v_value='参数值为3';
elseif uid=4 then
v_value='参数值为4';
else
v_value='其他情况';
end if;
return v_value;
end
$$
language plpgsql
调用函数:
例子:
create or replace function fn_case_col_when(uid int) returns text as
$$
declare
v_value text;
begin
case uid when 1 then
v_value = 'uid值为'||uid;
when 2 then
v_value = 'uid值为'||uid;
else
v_value = 'uid值不为1也不为2';
end case;
return v_value;
end
$$
language plpgsql
调用函数:
该语法中when ... then ... 是可以有多个的。上面 IF ... THEN ... ELSEIF ... THEN ... ELSE ... END IF语法中elseif也可以是多个的,但是elseif后不需要else 直接跟end if结果判断不出错,而该语法中when ... then 后面不跟else,创建函数时不会报错,但调用时,如果没有值符合when 中的值时,调用会报错。
如:错误示例
create or replace function fn_case_col_when_erro(uid int) returns text as
$$
declare
v_value text;
begin
case uid when 1 then
v_value = 'uid值为'||uid;
when 2 then
v_value = 'uid值为'||uid;
end case; --缺少else直接end case
return v_value;
end
$$
language plpgsql
调用函数:
如上,满足函数里判断条件时,不报错,不满足时,报错。
该case属于搜索case,when 后面可以赋予不同的参数布尔表达式(= 号左、右边的参数均可变)
例子:
create or replace function fn_casewhen_expression(uid int,uname varchar) returns text as
$$
declare
v_value text;
begin
case when uid = 1 then
v_value = 'UID或UNAME满足条件';
when uname = '张三' then
v_value = 'UID或UNAME满足条件';
else
v_value = 'UID和UNAME都不满足条件';
end case;
return v_value;
end
$$
language plpgsql
调用函数:
如上,函数逻辑是只要uid = 1 或者uname = ‘张三’ ,v_value的返回值就为 “UID或UNAME满足条件”
但第一种case: CASE ... WHEN ... THEN ... ELSE ... END CASE 只能判断“=”号右边的值,等号左边的参数是固定的。
如果else不存在,照样会抛出异常:ERROR: 20000: case not found
提示: CASE statement is missing ELSE part.
PL/pgSQLL中通过Loop、EXIT、CONTINUE、WHILE、FOR和FOREACH语句,可以安排PL/pgSQL重复执行一系列命令。
注意:LOOP ... END LOOP 语法避免单独使用,单独使用是死循环,一定要有跳出循环的语句(exit 或者直接return结束函数)
语法:
(1)LOOP
-- 一些计算
IF count > 0 THEN
EXIT; -- 退出循环
END IF;
END LOOP;
(2)LOOP
-- 一些计算
EXIT when count > 0; -- 退出循环
END LOOP;
例子1:
create or replace function fn_loop_exit() returns text as
$$
declare
v_value int default 0;
v_result text;
begin
loop
v_value = v_value + 1;
raise notice 'LOOP循环%次',v_value;
if v_value > 5 then
v_result = '退出循环v_value='||v_value;
EXIT; --退出循环
end if;
end loop;
return v_result;
end
$$
language plpgsql
调用函数:
例子2:例子中的if可以直接改写成 EXIT when expression
create or replace function fn_loop_exit() returns text as
$$
declare
v_value int default 0;
v_result text;
begin
loop
v_value = v_value + 1;
raise notice 'LOOP循环%次',v_value;
EXIT when v_value > 5; --退出循环
end loop;
return '退出循环v_value='||v_value;
end
$$
language plpgsql
调用函数:
语法:
LOOP
-- 一些计算
EXIT WHEN boolean-expression1;
CONTINUE WHEN boolean-expression2;
-- 一些操作
END LOOP;
当boolean-expression2为真时,continue生效,会使得结束本次循环直接跳到下次循环(一些操作 将不会执行)。当boolean-expression2为假时,continue无效,则其后面的一些操作会执行。
如:
LOOP
-- 一些计算
EXIT WHEN count > 100;
CONTINUE WHEN count < 50;
-- 一些操作
END LOOP;
当count IN [50 .. 100] 的时候,一些操作会执行。
例子:
create or replace function fn_loop_continue() returns void as
$$
declare
v_value int default 0;
begin
loop
v_value = v_value + 1;
exit when v_value > 5;
continue when v_value < 3;
raise notice 'continue后循环第%次',v_value;
end loop;
end
$$
language plpgsql
调用函数:
如上,当v_value in [3,5]时,raise notice执行。
语法:
[ <<label>> ]
WHILE boolean-expression LOOP
statements
END LOOP [ label ];
每次进入循环体之前检查一遍表达式,只要boolean-expression表达式为真,就会进入一次循环体。
例子:
create or replace function fn_loop_while() returns void as
$$
declare
v_value int default 0;
begin
raise notice 'while循环开始=======';
while v_value < 6 loop
v_value = v_value + 1;
raise notice '循环第%次',v_value;
end loop;
raise notice 'while循环结束=======';
end
$$
language plpgsql
调用函数:
如上:当v_value in[1,5]时,都会进入循环体执行相关操作,当v_value = 5时进入循环体,此时v_value本次循环后为v_value=6,再次进入循环体时检查v_value<6为false,则结束循环。
语法:
[ <<label>> ]
FOR name IN [ REVERSE ] beginval .. endval [ BY expression ] LOOP
statements
END LOOP [ label ];
name 变量会自动定义为integer并在循环内存在
beginval 循环开始name的值
endval 结束循环name的值
BY 没有指定,步长为1,指定了则步长为指定值。
REVERSE 省略则beginval到endval为增加(每次增加步长值),指定则beginval到endval为减除(每次减除步长值)
例子:
create or replace function fn_loop_forint() returns void as
$$
begin
raise notice '第一个for循环开始====';
for i in 1..5 loop
raise notice 'i的值为:%',i;
end loop;
raise notice '第二个for循环开始====';
for i in 1..5 by 2 loop
raise notice 'i的值为:%',i;
end loop;
raise notice '第三个for循环开始====';
for i in reverse 5..1 by 2 loop
raise notice 'i的值为:%',i;
end loop;
end;
$$
language plpgsql
调用函数:
语法:
静态
[ <<label>> ]
FOR target IN query LOOP
statements
END LOOP [ label ];
动态
[ <<label>> ]
FOR target IN EXECUTE text_expression [USING expression[,...]] LOOP
statements
END LOOP [ label ];
query 是一条查询语句,它会返回一个查询结果集
target 是一个记录变量、行变量或者逗号分隔的标量变量列表,需要事先定义。
EXECUTE 表示动态执行命令
在此循环中,每循环一次,target被赋予来自query的一行,
例子:
create or replace function fn_loop_query() returns void as
$$
declare
v_value record;
count int default 0;
begin
raise notice '循环开始========';
for v_value in select * from t_test loop
count = count + 1;
raise notice '第%次循环,name值为:%',count,v_value.name;
raise notice '第%次循环,age值为:%',count,v_value.age;
raise notice '第%次循环,code值为:%',count,v_value.code;
end loop;
end
$$
language plpgsql
调用函数:
使用此FOR语法与return next连用可以用来函数返回数据集。如例子2.3中方式一与方式二
FOREACH与FOR循环很像,区别在于FOR是通过SQL返回行进行迭代,而FOREACH是通过一个数组值得元素来迭代。
语法:
[ <<label>> ]
FOREACH target [ SLICE number ] IN ARRAY expression LOOP
statements
END LOOP [ label ];
target 变量
SLICE 当省略或者number为0时,遍历数组个体元素。当number为一个不大于数组维度的整数时,FOREACH会通过number的值来对数组进行切片(如number为1,则将数组切成多个维度为一的数组,当numeric为2时则将数组切成多个维度为2的数组)。
例子:
create or replace function fn_foreach(int[]) returns void as
$$
declare
x int;
begin
foreach x slice 0 in array $1
loop
raise notice '输出value = %',x;
end loop;
end
$$
language plpgsql;
create or replace function fn_foreach_slice(int[]) returns void as
$$
declare
x int[];
begin
foreach x slice 1 in array $1
loop
raise notice '输出row = %',x;
end loop;
end
$$
language plpgsql
调用函数:
create or replace function fn_foreach_slice_number(int[]) returns void as
$$
declare
x int[];
begin
foreach x slice 2 in array $1
loop
raise notice '输出row = %',x;
end loop;
end
$$
language plpgsql
对比结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。