ref: https://www.postgresql.org/docs/9.6/static/plpgsql-structure.html
一. 函數結構
CREATE FUNCTION somefunc(integer, text) RETURNS integer AS 'function body text' LANGUAGE plpgsql;
PL/pgSQL是塊結構(block-structured)語言,上面示例里的function body必須是一個塊(block),塊結構如下
[ <<label>> ] [ DECLARE declarations ] BEGIN statements END [ label ];
塊可以嵌套,嵌套塊里可以通過外層塊的標簽來調用外層塊的同名變量,示例:
CREATE FUNCTION somefunc() RETURNS integer AS $$ << outerblock >> DECLARE quantity integer := 30; BEGIN RAISE NOTICE 'Quantity here is %', quantity; -- Prints 30 quantity := 50; -- -- Create a subblock -- DECLARE quantity integer := 80; BEGIN RAISE NOTICE 'Quantity here is %', quantity; -- Prints 80 RAISE NOTICE 'Outer quantity here is %', outerblock.quantity; -- Prints 50 END; RAISE NOTICE 'Quantity here is %', quantity; -- Prints 50 RETURN quantity; END; $$ LANGUAGE plpgsql;
* PL/pgSQL的BEGIN/END與事務無關,只起分隔塊的作用;
* Function和trigger不能發起或提交一個事務,只能運行在外部查詢發起的事務里,因為其沒有事務的上下文;
* EXCEPTION表達式可以處理存儲過程里的錯誤,類似Java里的catch(see: PLPGSQL-ERROR-TRAPPING)
二. 變量聲明(Declarations)
1. 塊聲明域
name [ CONSTANT ] type [ COLLATE collation_name ] [ NOT NULL ] [ { DEFAULT | := | = } expression ];
示例:
i integer; quantity numeric(5); quantity integer DEFAULT 32; url varchar := 'http://mysite.com'; id_user CONSTANT integer := 10;
2. 函數形參
函數形參主要有兩種方式調用
1) 命名參數,如:
CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$ BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql;
2) 通過$n調用,如
CREATE FUNCTION sales_tax(real) RETURNS real AS $$ DECLARE subtotal ALIAS FOR $1; BEGIN RETURN subtotal * 0.06; END; $$ LANGUAGE plpgsql;
如上的函數形參傳參方式都是值傳遞,可以通過OUT關鍵字將形參設置為引用傳遞,示例:
CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$ BEGIN tax := subtotal * 0.06; END; $$ LANGUAGE plpgsql;
這里跟前面示例的sales_tax功能一樣,只是前面是作為返回值返回,而這里將計算結果記錄在了引用傳遞的參數里,外部可以在調用函數后訪問tax變量獲取函數計算結果。這就像C里的指針變量一樣,也類似C#里參數的ref關鍵字。
3. Alias
可以給變量賦予別名
newname ALIAS FOR oldname;
示例
DECLARE prior ALIAS FOR old; updated ALIAS FOR new;
4. 復制數據類型(Copying Types)
variable%TYPE
%TYPE能獲取一個變量或列的數據類型。要聲明一個跟表users的列id_user同樣數據類型的變量,可以通過如下方式實現:
id_user users.id_user%TYPE;
通過復制數據類型的方式,我們可以在不知道引用對象數據類型的情況下就進行引用,更關鍵的是當引用對象的數據類型改變時,我們的引用代碼並不需要跟着改動。
5. 復制列(Row Types)
name table_name%ROWTYPE;
table_name%ROWTYPE可以復制整個表所有用戶定義的列(非OID或者其他表系統列)
示例
CREATE FUNCTION merge_fields(t_row table1) RETURNS text AS $$ DECLARE t2_row table2%ROWTYPE; BEGIN SELECT * INTO t2_row FROM table2 WHERE ... ; RETURN t_row.f1 || t2_row.f3 || t_row.f5 || t2_row.f7; END; $$ LANGUAGE plpgsql; SELECT merge_fields(t.*) FROM table1 t WHERE ... ;