控制结构

最近更新时间:2022-09-02 15:31:49

我的收藏

判断语句

IF...THEN...END IF

postgres=# CREATE OR REPLACE FUNCTION f26() RETURNS VOID AS
postgres-# $$
postgres$# BEGIN
postgres$# IF random()>0.5 THEN
postgres$# RAISE NOTICE '随机数大于0.5';
postgres$# END IF;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# select f26();
NOTICE: 随机数大于0.5
f26
-----

(1 row)

postgres=#

IF...THEN...ELSE...END IF

postgres=# CREATE OR REPLACE FUNCTION f26() RETURNS VOID AS
postgres-# $$
postgres$# BEGIN
postgres$# IF random()>0.99 THEN
postgres$# RAISE NOTICE '随机数大于0.99';
postgres$# ELSE
postgres$# RAISE NOTICE '随机数小于或等于0.99';
postgres$# END IF;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# select f26();
NOTICE: 随机数小于或等于0.99
f26
-----

(1 row)

postgres=#

IF...THEN...ELSIF...THEN...ELSE...END IF

postgres=# CREATE OR REPLACE FUNCTION f26() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_float8 float8 := random();
postgres$# BEGIN
postgres$# IF v_float8>0.99 THEN
postgres$# RAISE NOTICE '随机数大于0.99';
postgres$# ELSIF v_float8>0.5 THEN
postgres$# RAISE NOTICE '随机数大于0.50';
postgres$# ELSIF v_float8>0.25 THEN
postgres$# RAISE NOTICE '随机数大于0.25';
postgres$# ELSE
postgres$# RAISE NOTICE '随机数小于或等于0.25';
postgres$# END IF;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f26();
NOTICE: 随机数大于0.50
f26
-----

(1 row)

CASE 语句

postgres=# CREATE OR REPLACE FUNCTION f26() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_float8 float8 := random();
postgres$# BEGIN
postgres$# CASE
postgres$# WHEN v_float8>0.99 THEN
postgres$# RAISE NOTICE '随机数大于0.99';
postgres$# WHEN v_float8>0.5 THEN
postgres$# RAISE NOTICE '随机数大于0.50';
postgres$# WHEN v_float8>0.25 THEN
postgres$# RAISE NOTICE '随机数大于0.25';
postgres$# ELSE
postgres$# RAISE NOTICE '随机数小于或等于0.25';
postgres$# END CASE;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f26();
NOTICE: 随机数大于0.50
f26
-----

(1 row)

循环语句

LOOP 循环

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_id INTEGER := 1;
postgres$# BEGIN
postgres$# LOOP
postgres$# RAISE NOTICE '%',v_id;
postgres$# EXIT WHEN random()>0.8;
postgres$# v_id := v_id + 1;
postgres$# END LOOP ;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: 1
NOTICE: 2
f27
-----

(1 row)
使用 EXIT 退出循环。
postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_id INTEGER := 1;
postgres$# v_random float8 ;
postgres$# BEGIN
postgres$# LOOP
postgres$# RAISE NOTICE '%',v_id;
postgres$# v_id := v_id + 1;
postgres$# v_random := random();
postgres$# IF v_random > 0.8 THEN
postgres$# RETURN;
postgres$# END IF;
postgres$# END LOOP ;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: 1
NOTICE: 2
NOTICE: 3
NOTICE: 4
NOTICE: 5
f27
-----

(1 row)

postgres=#
使用 RETURN 退出循环返回。

WHILE 循环

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_id INTEGER := 1;
postgres$# v_random float8 := random() ;
postgres$# BEGIN
postgres$# WHILE v_random > 0.8 LOOP
postgres$# RAISE NOTICE '%',v_id;
postgres$# v_id := v_id + 1;
postgres$# v_random = random();
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: 1
f27
-----

(1 row)

FOR 循环

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# BEGIN
postgres$# FOR i IN 1..3 LOOP
postgres$# RAISE NOTICE 'i = %',i;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: i = 1
NOTICE: i = 2
NOTICE: i = 3
f27
-----

(1 row)

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# BEGIN
postgres$# FOR i IN REVERSE 3..1 LOOP
postgres$# RAISE NOTICE 'i = %',i;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: i = 3
NOTICE: i = 2
NOTICE: i = 1
f27
-----

(1 row)
使用 REVERSE 递减。

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# BEGIN
postgres$# FOR i IN 1..8 BY 2 LOOP
postgres$# RAISE NOTICE 'i = %',i;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: i = 1
NOTICE: i = 3
NOTICE: i = 5
NOTICE: i = 7
f27
-----

(1 row)
使用 BY 设置步长。

FOR 循环查询结果

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_rec RECORD;
postgres$# BEGIN
postgres$# FOR v_rec IN SELECT * FROM public.t LOOP
postgres$# RAISE NOTICE '%',v_rec;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: (1,tdsql_pg)
NOTICE: (2,pgxz)
f27
-----

(1 row)

FOREACH 循环一个数组

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_random_arr float8[]:=ARRAY[random(),random()];
postgres$# v_random float8;
postgres$# BEGIN
postgres$# FOREACH v_random IN ARRAY v_random_arr LOOP
postgres$# RAISE NOTICE '%',v_random ;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: 0.452758576720953
NOTICE: 0.975814974401146
f27
-----

(1 row)

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_random_arr float8[][]:=ARRAY[ARRAY[random(),random()],ARRAY[random(),random()]];
postgres$# v_random float8;
postgres$# BEGIN
postgres$# FOREACH v_random SLICE 0 IN ARRAY v_random_arr LOOP
postgres$# RAISE NOTICE '%',v_random ;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: 0.0588191924616694
NOTICE: 0.368828620761633
NOTICE: 0.813376842066646
NOTICE: 0.415377039927989
f27
-----

(1 row)
循环会通过计算 expression 得到的数组的个体元素进行迭代。
postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_random_arr float8[][]:=ARRAY[ARRAY[random(),random()],ARRAY[random(),random()]];
postgres$# v_random float8[];
postgres$# BEGIN
postgres$# FOREACH v_random SLICE 1 IN ARRAY v_random_arr LOOP
postgres$# RAISE NOTICE '%',v_random ;
postgres$# END LOOP;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
NOTICE: {0.578366641886532,0.78098024148494}
NOTICE: {0.783956411294639,0.450278480071574}
f27
-----

(1 row)
通过一个正 SLICE 值,FOREACH 通过数组的切片而不是单一元素迭代。

其它控制语句

动态执行

postgres=# CREATE OR REPLACE FUNCTION f27(a_id INTEGER) RETURNS text AS
postgres-# $$
postgres$# DECLARE
postgres$# v_sql TEXT;
postgres$# v_mc TEXT;
postgres$# BEGIN
postgres$# v_sql := 'SELECT mc FROM t WHERE id='||a_id::TEXT;
postgres$# EXECUTE v_sql INTO v_mc;
postgres$# RETURN v_mc;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27(1);
f27
-------
tdsql_pg
(1 row)
动态执行就是拼 SQL 语句,然后使用 EXECUTE 命令执行。

执行一个没有结果的命令

postgres=# CREATE OR REPLACE FUNCTION f27() RETURNS void AS
postgres-# $$
postgres$# BEGIN
postgres$# perform f27(1);
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27();
f27
-----

(1 row)

postgres=#

获取执行结果

postgres=# DROP FUNCTION f27(INTEGER);
DROP FUNCTION
postgres=# CREATE OR REPLACE FUNCTION f27(a_id INTEGER) RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_mc TEXT;
postgres$# BEGIN
postgres$# SELECT mc INTO v_mc FROM t WHERE id=a_id;
postgres$# IF FOUND THEN
postgres$# RAISE NOTICE '查询到记录,值为%',v_mc;
postgres$# ELSE
postgres$# RAISE NOTICE '查不到记录' ;
postgres$# END IF;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27(1);
NOTICE: 查询到记录,值为tdsql_pg
f27
-----

(1 row)

postgres=# SELECT f27(3);
NOTICE: 查不到记录
f27
-----

(1 row)

获取影响行数

postgres=# CREATE OR REPLACE FUNCTION f27(a_id INTEGER) RETURNS VOID AS
postgres-# $$
postgres$# DECLARE
postgres$# v_mc TEXT;
postgres$# v_row_count BIGINT;
postgres$# BEGIN
postgres$# SELECT mc INTO v_mc FROM t WHERE id=a_id;
postgres$# GET DIAGNOSTICS v_row_count = ROW_COUNT;
postgres$# RAISE NOTICE '查询到的记录数为 % ',v_row_count;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION

postgres=# SELECT f27(1);
NOTICE: 查询到的记录数为 1
f27
-----

(1 row)
postgres=# SELECT f27(3);
NOTICE: 查询到的记录数为 0
f27
-----

(1 row)

俘获错误

错误俘获处理

postgres=# CREATE TABLE t_exception (id integer not null,nc text);
CREATE TABLE
postgres=# create unique index t_exception_id_uidx on t_exception using btree(id);
CREATE INDEX
postgres=# CREATE OR REPLACE FUNCTION f27(a_id integer,a_nc text) RETURNS TEXT AS
postgres-# $$
postgres$# BEGIN
postgres$# INSERT INTO t_exception VALUES(a_id,a_nc);
postgres$# RETURN '';
postgres$# EXCEPTION WHEN OTHERS THEN
postgres$# RETURN '执行出错';
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT f27(1,'tdsql_pg');
f27
-----

(1 row)

postgres=# SELECT f27(1,'tdsql_pg');
f27
----------
执行出错
(1 row)

获取错误相关信息

postgres=# CREATE OR REPLACE FUNCTION f27(a_id integer,a_nc text) RETURNS TEXT AS
postgres-# $$
postgres$# DECLARE
postgres$# v_sqlstate text;
postgres$# v_context text;
postgres$# v_message_text text;
postgres$# BEGIN
postgres$# INSERT INTO t_exception VALUES(a_id,a_nc);
postgres$# RETURN '';
postgres$# EXCEPTION WHEN OTHERS THEN
postgres$# GET STACKED DIAGNOSTICS v_sqlstate = RETURNED_SQLSTATE,
postgres$# v_message_text = MESSAGE_TEXT,
postgres$# v_context = PG_EXCEPTION_CONTEXT;
postgres$# RAISE NOTICE '错误代码 : %',v_sqlstate;
postgres$# RAISE NOTICE '出错信息 : %',v_message_text;
postgres$# RAISE NOTICE '发生异常语句 : %',v_context;
postgres$# RETURN '错误代码 : '||v_sqlstate || '\\n出错信息 : '||v_message_text|| '发生异常语句 : '||v_context;
postgres$# END;
postgres$# $$
postgres-# LANGUAGE plpgsql;
CREATE FUNCTION

postgres=# SELECT f27(1,'tdsql_pg');
NOTICE: 错误代码 : 23505
NOTICE: 出错信息 : node:16385, error duplicate key value violates unique constraint "t_exception_id_uidx"
NOTICE: 发生异常语句 : SQL statement "INSERT INTO t_exception VALUES(a_id,a_nc)"
PL/pgSQL function f27(integer,text) line 7 at SQL statement
f27
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
错误代码 : 23505\\n出错信息 : node:16385, error duplicate key value violates unique constraint "t_exception_id_uidx"发生异常语句 : SQL statement "INSERT INTO t_exception VALUES(a_id,a_nc)"+
PL/pgSQL function f27(integer,text) line 7 at SQL statement
(1 row)