postgresql學習-自定義函數

————————————————
版權聲明:本文爲CSDN博主「尚雲峯」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u011165335/article/details/99895650

在pg裏面,只有function
1.刪除函數 函數名+參數簽名
drop FUNCTION if exists HelloWorld2(varchar);

2.CREATE OR REPLACE FUNCTION 不允許你修改一個現有函數的返回類型。
– 要做這些事情,你必須刪除並重新創建函數。
–LANGUAGE plpgsql yelowbick只有過程,跟pgsql剛好相反

–入參:anyelement 基本類型 表類型 遊標
–返回:基本類型,記錄類型,遊標,json,table類型,數組

 --塊language plpgsql可以註釋掉   方便用來測試
do --language plpgsql
    $$
        begin
           raise notice 'ok';
        end;
    $$;

3.行對象row
select * from dept;
SELECT ROW(‘10’, ‘aaa’, ‘hhhh’)::dept;
– 記錄變量record類似於行類型變量,但是它們沒有預定義的結構,
– 只能通過SELECT或FOR命令來獲取實際的行結構,因此記錄變量在被初始化之前無法訪問,否則將引發運行時錯誤。
–注:RECORD不是真正的數據類型,只是一個佔位符。
 

4.LANGUAGE SQL

-- LANGUAGE SQL 簡單的DML語句
create or replace  FUNCTION func_get() RETURNS int AS
$$
select 1;
$$ LANGUAGE SQL;

select * from func_get();


create or replace function add_two(int,int)
returns int
as
$$
    select $1+$2;
$$ LANGUAGE sql;
select * from add_two(1,2);

--returning返回更新前的值
drop function update_emp(varchar);
create or replace function update_emp(varchar)
returns varchar
as
$$
    update emp set ename=$1||'ysy' where ename=$1
    returning ename;
$$ LANGUAGE sql;
select * from update_emp('SMITH');


--複合類型
create or replace function sel_emp(emp)
returns varchar
as
$$
   select $1.ename;
$$ LANGUAGE sql;
 select sel_emp(e.*) from emp e;


--輸出類型  這裏等價於add_two
CREATE FUNCTION add_two2 (IN x int, IN y int, OUT sum int) AS $$
        SELECT $1 + $2*2;
$$ LANGUAGE SQL;

CREATE FUNCTION add_two3 (IN x int, IN y int, OUT sum1 int,out sum2 int) AS
$$
        SELECT $1 + $2*2,$1 + $2;
$$ LANGUAGE SQL;
select * from add_two3(1,2);


--返回集合-----------------------------------------
-- 類型爲emp,默認之返回第一條記錄
CREATE FUNCTION getfoo1() RETURNS emp AS $$
        SELECT * FROM emp ;
    $$ LANGUAGE SQL;
select * from getfoo1();

--如果要全部返回setof table
CREATE FUNCTION getfoo2() RETURNS  setof emp AS $$
        SELECT * FROM emp ;
    $$ LANGUAGE SQL;
select * from getfoo2();
--可以訪問指定列
select  (getfoo2()).ename;


drop function getfoo2_1;
--可以指定返回表的具體字段類型
create or replace function getfoo2_1() RETURNS   emp.ename%type  AS $$
        SELECT ename FROM emp ;
    $$ LANGUAGE SQL;
select * from getfoo2_1();


--可以返回記錄類型
create or replace function  getfoo3() RETURNS  record AS $$
        SELECT empno,ename FROM emp ;
    $$ LANGUAGE SQL;
select  getfoo3() ;
--如何訪問記錄類型結果集呢   類型要一致,這個聲明確實有點不方便
select t.ename from  getfoo3() t (empno integer,ename varchar);

--自定義返回類型
create  type rec_type as (empno int,ename varchar);
create or replace function  getfoo4() RETURNS  rec_type AS $$
        SELECT empno,ename FROM emp ;
    $$ LANGUAGE SQL;
--這裏type裏面指定了,不需要聲明
select t.ename from  getfoo4() t ;


--多態
 CREATE FUNCTION make_array(anyelement, anyelement) RETURNS anyarray AS $$
        SELECT ARRAY[$1, $2];
    $$ LANGUAGE SQL;
select * from make_array(1,1);
--字符要指定類型
select * from make_array('a'::text,'n'::text);

--  如果PL/pgSQL函數的返回類型爲多態類型(anyelement或anyarray),那麼函數就會創建一個特殊的參數:$0。
--  我們仍然可以爲該變量設置別名。
    create or replace function  add_three_values(v1 anyelement, v2 anyelement, v3 anyelement)
    RETURNS anyelement AS $$
    DECLARE
        result ALIAS FOR $0;
    BEGIN
        result := v1 + v2 + v3;
        RETURN result;
        --RETURN (v1 + v2 + v3); --等價
    END;
    $$ LANGUAGE plpgsql;
select * from add_three_values(1,2,3);

--重載
  CREATE FUNCTION test(int, real) RETURNS ...
  CREATE FUNCTION test(int, varchar) RETURNS ...

5.language plpgsql

返回集合類型和json的方式如下:

 

-- language plpgsql
--返回record
create or replace function getRecord()
    returns record
as
$$
declare
    v_arr record;
begin
    v_arr := ('aaa'::varchar,'bbb'::varchar);
    return v_arr;
end ;
$$ language plpgsql;

select t.* from getRecord() t (a varchar,b varchar);

--返回數組
create or replace function getArr()
    returns int[]
as
$$
declare
    v_arr int[];
begin
    v_arr := array [1,2];
    return v_arr;
end ;
$$ language plpgsql;


--返回json
create or replace function getJson()
    returns json
as
$$
declare
    v_arr json;
begin
    v_arr := '{"name":"李易峯","sex":"男"}';
    return v_arr;
end ;
$$ language plpgsql;

--測試
do
$$
declare
    v_rec1 varchar;
    v_rec2 varchar;
    v_arr int[];
    v_json json;
begin
    --record
    select t.* into v_rec1,v_rec2 from getRecord() t (a varchar,b varchar);
    raise notice 'record=,%,%',v_rec1,v_rec2;
    --arr
    v_arr:=getArr();
    raise notice 'arr=,%',v_arr[1];
    v_json:=getJson();
    raise notice 'json=,%',v_json->>'name';
end;
$$;

6.遊標操作

--遊標操作

--返回所有結果集
create or replace function  getRcord() RETURNS  setof record AS $$
    declare
       rec record;
        --oracle cursor c_emp is ...
       c_emp cursor  for select ename from emp;
      --pg 不存在c_emp%rowType;這種類型,用record來接受
    begin
        for rec in c_emp  loop
        --將當前行的結果集插入rec
          return next rec;
        end loop;
        return ;
    end;
    $$ language plpgsql;
--需要聲明
select * from  getRcord() t (ename varchar);


create or replace function  getRcord1_2(refcursor) RETURNS  setof refcursor AS $$
    declare
       rec record;
       ref alias for $1;
    begin
        open ref for select * from emp;
        return next ref;
    end;
    $$ language plpgsql;
select getRcord1_2('a'::refcursor);





--返回text 方式1
create or replace function  getRcord2() RETURNS  text  AS $$
    declare
       rec record;
       v_text text;
       c_emp cursor  for select * from emp;
    begin
        v_text:='';
       open c_emp;
       loop
           fetch  c_emp into rec;
           exit when not FOUND;
           v_text:=v_text||','||rec.ename;
       end loop;
       close c_emp;
    return v_text;
    end;
    $$ language plpgsql;
select  getRcord2();

--返回text 方式2
drop function getref;
create or replace function  getRcord3() RETURNS  text AS $$
    declare
     ref refcursor;
     v_rec record;
     v_text text:='';
    begin
        --open ref for  SELECT empno,ename FROM emp ;
        open ref for execute 'SELECT empno,ename FROM emp' ;
        --動態遊標,只能loop循環,這點跟oracle是一樣的
        loop
           fetch  ref into v_rec;
           exit when not found;
           v_text:=v_text||','||v_rec.ename;
        end loop;
        close ref;
        return v_text;
    exception when others
        then
        raise exception 'error,%',SQLERRM;
    end;
    $$ language plpgsql;
select * from getRcord3();

--動態遊標
/*PL/pgSQL 函數可以向調用者返回遊標。 這個功能用於從函數裏返回多行或多列。要想這麼做的時候, 該函數打開遊標並且把該遊標的名字返回給調用者。 調用者然後從遊標裏FETCH行。 遊標可以由調用者關閉,或者是在事務結束的時候自動關閉。
函數返回的遊標名可以由調用者聲明或者自動生成。 要聲明一個信使的名字,只要再打開遊標之前,給 refcursor 變量賦予一個字串就可以了。 refcursor 變量的字串值將被 OPEN 當作下層的信使的名字使用。 不過,如果 refcursor 變量是空,那麼 OPEN 將自動生成一個和現有信使不衝突的名字, 然後將它賦予 refcursor 變量。
注意: 一個綁定的遊標變量其名字初始化爲對應的字串值,因此信使的名字和遊標變量名同名, 除非程序員再打開遊標之前通過賦值覆蓋了這個名字。但是一個未綁定的遊標變量初始化的時候缺省是空, 因此它會收到一個自動生成的唯一的名字,除非被覆蓋。
下面的例子顯示了一個調用者聲明遊標名字的方法:*/
create or replace   FUNCTION ger_ref(refcursor) RETURNS refcursor AS
$$
BEGIN
       OPEN $1 FOR SELECT ename FROM emp;
       RETURN $1;
END;
$$ LANGUAGE plpgsql;

--只能用一次那個遊標名,用
BEGIN;
SELECT ger_ref('funccursor');
FETCH ALL IN funccursor;
COMMIT;

--下面的例子使用了自動生成的遊標名:
drop FUNCTION if exists ger_ref2;
 create or replace FUNCTION ger_ref2() RETURNS refcursor AS
 $$
 DECLARE
     ref refcursor;
 BEGIN
     OPEN ref FOR SELECT ename FROM emp;
     RETURN ref;
 END;
 $$ LANGUAGE plpgsql;

BEGIN;
SELECT ger_ref2();
FETCH ALL IN "<unnamed portal 1>";
COMMIT;

7.函數的調用

--函數的調用
-- yellow brick 是call和execute
-- select into 對於返回結果多行的,指揮取一行,如果結果爲空,不會報錯,跟oracle不一樣
drop function into_test;
create or replace function into_test()
returns text as
    $$
     declare
         v_name emp.ename%type;
     begin
         select e.ename into v_name from emp e;
         if found then
             raise notice 'ename=%',v_name;
         end if;
         return 'ok';
     end;

    $$
    language plpgsql;

select into_test();

do $$
    declare
    v_text text;
begin
    --方式0
    --v_text:=into_test();
    --方式1
	--execute 'into_test()';
    --方式2 忽略返回值
    --perform into_test();
    -- 錯誤select into_test();
end
$$;

8.pgsql的批量操作

https://yq.aliyun.com/articles/54786?spm=a2c4e.11153940.0.0.28e2231f3pNJsx

https://yq.aliyun.com/articles/74420?do=login&accounttraceid=b0fcec2d-bb75-4f55-89a2-81fbcfb21110&do=login
————————————————
版權聲明:本文爲CSDN博主「尚雲峯」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u011165335/article/details/99895650

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章