greenplum自定義函數


CREATE [OR REPLACE] FUNCTION proname(argname argtype) [returns {[SETOF] rettype|TABLE(argname argtype|like other table)}]
{language langname|IMMUTABLE|STABLE|VOLATILE}

1.CREATE OR REPLACE FUNCTION不允許改變已經存在的函數的返回值類型,如果要這樣做,那么需要將原函數刪除,然后重新創建新的函數。
2.任何被歸為STABLE 和VOLATILE類型的函數不能再segment上執行,因為會導致segment實例之間的數據不一致。
3.如果該函數不支持返回一個值,則使用void作為返回類型。只有OUT和INOUT參數時,RETURNS語句可以被省略。
4.SETOF修飾符表明函數會返回一個item集合, 而不是一個item。
5.IMMUTABLE|STABLE|VOLATILE該屬性會告訴查詢優化器關於函數的行為如果省略, VOLATILE 為默認值.
IMMUTABLE說明函數不能夠修改數據庫,並且對於給定相同的參數值的情況總是返回相同的結果。
STABLE 說明函數不能修改數據庫
VOLATILE 說明函數可以修改事件(event), 所以沒有做任何優化
6.CALLED ON NULL INPUT|RETURNS NULL ON NULL INPUT|STRICT
CALLED ON NULL INPUT (默認值)說明當一些參數為null時該函數會被調用。
RETURNS NULL ON NULL INPUT和 STRICT 說明函數總是返回null,
7.plpgsql 的動態語句 格式“execute <varchar變量的sql語句>”plpgsql沒有 execute [into <variable_list>] [using <variable_list>] 的寫法
8.plpgsql 不使用 游標,而是用 for 循環代替。
9.plpgsql 的異常信息 變量: sqlstate,sqlerrm。沒有sqlcode。ORACLE 的 異常信息 變量:sqlcode,sqlerrm。
10.查詢過程編譯過的 select prosrc from pg_proc where proname="存儲過程名稱"

Examples
一個簡單的加法函數:

CREATE FUNCTION add(integer, integer) RETURNS integer

AS 'select $1 + $2;'

LANGUAGE SQL

IMMUTABLE

RETURNS NULL ON NULL INPUT;

增加一個整形數的值,使用參數的名字, 使用 PL/pgSQL:

CREATE OR REPLACE FUNCTION increment(i integer) RETURNS

integer AS $$

BEGIN

RETURN i + 1;

END;

$$ LANGUAGE plpgsql;

對於一個PL/pgSQL函數,增加每次查詢時的segment主機內存:

CREATE OR REPLACE FUNCTION function_with_query() RETURNS

SETOF text AS $$

BEGIN

RETURN QUERY

EXPLAIN ANALYZE SELECT * FROM large_table;

END;

$$ LANGUAGE plpgsql

SET statement_mem='256MB';

連接 https://blog.csdn.net/jmx_bigdata/article/details/84316863


異常
create or replace function prc_test(in par1 text,in par2 numeric,in par3 integer)
returns void as $$
declare
v_msg varchar(4000);
begin
insert into table1 values(par1,par2,par3);
EXCEPTION
WHEN OTHERS THEN
v_msg := substr(SQLERRM, 1, 2000);
PERFORM my_err(ic_cendat, ic_jobid, ic_seq, v_msg);
END;
end;
$$ language plpgsql;

 

循環 while
CREATE OR REPLACE FUNCTION fun_gp_test_xxx_20181026(v_month int)
RETURNS INT AS
$BODY$

declare
v_num int;
v_count int;

begin
v_num := 0;
v_count := 1;

while v_count > 0 loop
v_num := v_num + 1;
select count(1) into v_count from temp_cwh_test_1106 where split_part(rate_item,';',v_num) <> '';
if v_count > 0 then
insert into temp_cwh_test_1106_02 select serv_id,usage_date,latn_id,split_part(rate_item,';',v_num) from temp_cwh_test_1106 where split_part(rate_item,';',v_num) <> ''; ---- 需要提前建好temp_cwh_test_1106_02表
end if;
end loop;
return 0;
end;

循環 for
說明: loop variable of loop over rows must be a record or row variable or list of scalar variables。
--創建 函數
drop function zzhtest.fnc_test();
create or replace function zzhtest.gnc_test()
returns varchar as $$
declare
rec record;
vv_result varchar(200);
begin
for rec in (select brand_code,brand_name from zzhtest.t_brand ) loop
insert into zzhtest.t_brand_bak values(rec.brand_code,rec.brand_name);
end loop;
vv_result := 'successful';
return vv_result;
exception
when others then
vv_result := substr(sqlstate ||':'|| sqlerrm,1,200);
end;
$$ language plpgsql;

2. for i in n1..n2 loop end loop
drop function zzhtest.fnc_test();
create or replace function zzhtest.gnc_test()
returns integer as $$
declare
vi_sum integer default 0;
begin
for i in 1..100 loop --此處i無需定義
vi_sum := vi_sum + i;
end loop;
return vi_sum;
exception
when others then
return -1;
end;

分支 if then elsif then else end if
drop function zzhtest.fnc_test(integer,integer);

create or replace function zzhtest.gnc_test(
in iv_a integer,
in iv_b integer
)
returns varchar as $$
declare
vv_result varchar(10);
begin
if iv_a = iv_b then
vv_result := iv_a ||'與'|| iv_b ||'相等';
elsif iv_a > iv_b then
vv_result := iv_a ||'大於'|| iv_b;
else
vv_result := iv_a ||'小於'|| iv_b;
end if;
return vv_result;
exception
when others then
vv_result := substr(sqlstate ||':'|| sqlerrm,1,200);
return vv_result;
end;
$$ language plpgsql;

【greenplum 的 靜態語句 和 動態語句】
drop function zzhtest.fnc_test(varchar,varchar);

create or replace function zzhtest.fnc_test(
in iv_brand_code varchar,
in iv_brand_name varchar
)
returns varchar as $$
declare vi_cnt integer;
declare vv_sql varchar(100);
declare vv_result varchar(200);
begin
--select into語句
select count(*) into vi_cnt from zzhtest.t_brand where brand_code = upper(iv_brand_code);
--greenplum子程序中沒有 execute into 的寫法
--vv_sql := ' select count(*) from zzhtest.t_brand where brand_code = upper('''||iv_brand_code||''')';
--execute vv_sql into vi_cnt;

if vi_cnt = 0 then
--insert into zzhtest.t_brand values(upper(iv_brand_code),upper(iv_brand_name)); --靜態語句
vv_sql := ' insert into zzhtest.t_brand values(upper('''||iv_brand_code||'''),upper('''||iv_brand_name||'''))';
execute vv_sql; --動態語句
else
--update zzhtest.t_brand set brand_name = upper(iv_brand_name) where brand_code = upper(iv_brand_code); -- 靜態語句
vv_sql := 'update zzhtest.t_brand set brand_name = upper('||quote_literal(iv_brand_name)||') where brand_code = upper('||quote_literal(iv_brand_code)||') ';
execute vv_sql; --動態語句
end if;
vv_result := 'successful';
return vv_result;
exception
when others then
vv_result := substr(sqlstate ||':'|| sqlerrm,1,200); --異常信息
end;
$$ language plpgsql;

 指定表結構方式:

CREATE OR REPLACE FUNCTION ads.fv_repay_detail() RETURNS 
TABLE( product_id bigint, real_date varchar, principal_tot NUMERIC, principal NUMERIC, interest NUMERIC) AS 
$$
SELECT product_id, real_date, principal_tot, principal, interest from tb_repay_plan
$$ LANGUAGE sql;

使用已有表的結構:
CREATE OR REPLACE FUNCTION  table_name1 () RETURNS 
SETOF table_name1 AS 
$body$ 
SELECT * from table_name1; 
$body$ 
LANGUAGE 'sql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM