|
23.6. 控制结构控制结构可能是 PL/pgSQL 中最有用的(以及最重要) 的部分了.利用 PL/pgSQL 的控制结构, 你可以以非常灵活而且强大的方法操纵 PostgreSQL 的数据. 23.6.1. 从函数返回
RETURN expression ; 函数结束并且表达式 expression 的值将返回给上层执行器. 表达式的结果将自动转换为函数返回类型,就象我们在赋值里描述的那样. 函数的返回值不能不加定义.如果控制到达函数顶层块的末尾还没有 碰到一条 RETURN 语句,那么将产生一个运行时错误. 23.6.2. 条件IF 语句让你可以根据某种条件执行命令. PL/pgSQL 有四种形式的 IF∶IF-THEN,IF-THEN-ELSE,IF-THEN-ELSE IF, IF-THEN-ELSIF-THEN-ELSE. 23.6.2.1. IF-THEN
IF boolean-expression THEN statements END IF; IF-THEN 语句是 IF 的最简单形式.如果条件为真, 在 THEN 和 END IF 之间的语句将被执行. 否则,将忽略它们. IF v_user_id <> 0 THEN UPDATE users SET email = v_email WHERE user_id = v_user_id; END IF;
23.6.2.2. IF-THEN-ELSE
IF boolean-expression THEN statements ELSE statements END IF; IF-THEN-ELSE 语句增加了 IF-THEN 的分支,让你可以声明 在条件计算为 FALSE 的时候执行的语句. IF parentid IS NULL or parentid = '''' THEN RETURN fullname; ELSE RETURN hp_true_filename(parentid) || ''/'' || fullname; END IF; IF v_count > 0 THEN INSERT INTO users_count(count) VALUES(v_count); RETURN ''t''; ELSE RETURN ''f''; END IF;
23.6.2.3. IF-THEN-ELSE IFIF 语句可以嵌套并且在下面的例子中∶ IF demo_row.sex = ''m'' THEN pretty_sex := ''man''; ELSE IF demo_row.sex = ''f'' THEN pretty_sex := ''woman''; END IF; END IF;
如果你使用这种形式,那么你实际上就是在另外一个 IF 语句的 ELSE 部分嵌套了一个 IF 语句.因此你需要一个 END IF 语句 给每个嵌套的 IF,另外还要一个给父 IF-ELSE 用. 这么干是可以的,但是如果我们有太多候选项需要检查,那么就会变得很乏味. 23.6.2.4. IF-THEN-ELSIF-ELSE
IF boolean-expression THEN statements [ ELSIF boolean-expression THEN statements [ ELSIF boolean-expression THEN statements ... ] ] [ ELSE statements ] END IF; IF-THEN-ELSIF-ELSE 提供了一种更方便的方法用于在一条语句中 检查许多候选.形式上它和嵌套的 IF-THEN-ELSE-IF-THEN 命令相同, 但是只需要一个 END IF. 这里是一个例子∶ IF number = 0 THEN result := ''zero''; ELSIF number > 0 THEN result := ''positive''; ELSIF number < 0 THEN result := ''negative''; ELSE -- 另外一个唯一的可能是它是 NULL result := ''NULL''; END IF;
最后的 ELSE 段是可选的. 23.6.3. 简单循环使用 LOOP,WHILE,FOR 和 EXIT 语句,你可以控制你的 PL/pgSQL 函数重复一系列明令. 23.6.3.1. LOOP
[
<<label>>
]
LOOP
statements
END LOOP;
LOOP 定义一个无条件的循环,无限循环,直到由 EXIT 或者 RETURN 语句终止. 可选的标签可以由 EXIT 语句使用,用于在嵌套循环中声明应该结束哪一层循环. 23.6.3.2. EXIT
EXIT [ label ] [ WHEN expression ]; 如果没有给出 label , 那么退出最内层的循环,然后执行跟在 END LOOP 后面的语句. 如果给出 label , 那么它必须是当前或者更高层的嵌套循环块或者块的标签. 然后该命名块或者循环就会终止,而控制落到对应循环/块的 END 语句后面的语句上. 如果出现了 WHEN,循环退出只发生在声明的条件为真的时候, 否则控制会落到 EXIT 后面的语句上. 例子∶ LOOP -- 一些计算 IF count > 0 THEN EXIT; -- exit loop END IF; END LOOP; LOOP -- 一些计算 EXIT WHEN count > 0; END LOOP; BEGIN -- 一些计算 IF stocks > 100000 THEN EXIT; -- 非法,不能用 EXIT 退出到 LOOP 外面. END IF; END;
23.6.3.3. WHILE
[
<<label>>
]
WHILE
expression
LOOP
statements
END LOOP;
只要条件表达式为真,WHILE 语句就会不停在一系列语句上进行循环. 条件是在每次进入循环体的时候检查的. 比如∶ WHILE amount_owed > 0 AND gIFt_certIFicate_balance > 0 LOOP -- 可以在这里做些计算 END LOOP; WHILE NOT BOOLEAN_expression LOOP -- 可以在这里做些计算 END LOOP;
23.6.3.4. FOR (整数 for 循环)
[ <<label>> ] FOR name IN [ REVERSE ] expression .. expression LOOP statements END LOOP; 这种形式的 FOR 对一定范围的整数数值进行迭代的循环.变量 name 会自动定义为整数类型并且只在 循环里存在.给出范围上下界的两个表达式在进入循环的时候计算一次. 迭代步进值总是为 1,但如果声明了 REVERSE 就是 -1. 一些整数 FOR 循环的例子∶ FOR i IN 1..10 LOOP -- 这里可以放一些表达式 RAISE NOTICE ''i IS %'',i; END LOOP; FOR i IN REVERSE 10..1 LOOP -- 这里可以放一些表达式 END LOOP;
23.6.4. 遍历查询结果使用不同类型的 FOR 循环,你可以遍历一个查询的结果并且相应地 操作哪些数据.语法是∶
[
<<label>>
]
FOR
record | row
IN
select_query
LOOP
statements
END LOOP;
这里的记录或者行变量将相继被赋予所有来自 SELECT 查询的行, 并且循环体将为每行执行一次.下面是一个例子∶
CREATE FUNCTION cs_refresh_mviews () RETURNS INTEGER AS ' DECLARE mviews RECORD; BEGIN PERFORM cs_log(''Refreshing materialized views...''); FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP -- 现在 "mviews" 里有了一条来自 cs_materialized_views 的记录 PERFORM cs_log(''Refreshing materialized view '' || quote_ident(mview.mv_name) || ''...''); TRUNCATE TABLE quote_ident(mview.mv_name); INSERT INTO quote_ident(mview.mv_name) || '' '' || mview.mv_query; END LOOP; PERFORM cs_log(''Done refreshing materialized views.''); RETURN 1; END; ' LANGUAGE 'plpgsql'; 如果循环是用一个 EXIT 语句终止的,那么在循环之后你仍然可以 访问最后赋值的行. FOR-IN-EXECUTE 语句是遍历所有记录的另外一种方法∶
[
<<label>>
]
FOR
record | row
IN EXECUTE
text_expression
LOOP
statements
END LOOP;
这个例子类似前面的形式,只不过源 SELECT 语句声明为了一个 字串表达式,这样它在每次进入 FOR 循环的时候都会重新计算和 生成查询规划.这样就允许程序员在一个预先规划好了的查询所获得 的速度和一个动态查询所获得的灵活性(就象一个简单的 EXECUTE 语句那样)之间进行选择.
|