存儲過程(SQL stored procedures),通常指數據庫中存放在一起的一系列SQL。您在使用存儲過程時,可以指定存儲過程的名字并使用參數(parameters),并在合適的時候調用存儲過程實現相同或者不同的業務。本文將介紹存儲過程的使用方法。
背景信息
AnalyticDB PostgreSQL 6.0版中,函數(Function)雖然可以實現大部分存儲過程功能,但是使用函數代替存儲過程的方式會產生額外的工作量,且函數內部不支持事務控制,無法完全代替存儲過程功能。因此AnalyticDB PostgreSQL 7.0版新增了存儲過程功能。
在7.0版本,您可以直接在存儲過程中控制事務。Oracle等傳統數倉的業務遷移至AnalyticDB PostgreSQL版時,可以直接使用存儲過程功能,不需要改造業務SQL。
存儲過程的特性
AnalyticDB PostgreSQL 7.0版的內核版本升級至PostgreSQL 12,可以較好地支持存儲過程能力。通過合理地使用存儲過程,您可以在業務開發中可以獲得以下收益:
存儲過程整合了一些列SQL,并分隔不同業務的SQL。這種特性使得存儲過程易于維護,極大地提升數據庫開發者的效率。
調用存儲過程非常簡單,數據庫開發者可以高效地在不同業務場景中復用存儲過程。
不同的存儲過程可以賦予不同的用戶權限,幫助提升數據庫使用的安全性。
注意事項
暫不支持在DMS上使用存儲過程,如需使用存儲過程,建議您在客戶端工具psql上進行操作。
語法及參數介紹
具體信息,請參見CREATE PROCEDURE。
存儲過程與函數的區別
AnalyticDB PostgreSQL 6.0版的函數(Function)可以實現大部分的存儲過程功能,通常建議您使用函數來實現存儲過程業務,但是存儲過程仍然是許多AnalyticDB PostgreSQL版用戶、及PostgreSQL從業者們期待已久的功能,具體原因主要為:
存儲過程使用CREATE PROCEDURE語法,并通過CALL調用,符合SQL語法標準,減少用戶從其它支持存儲過程數據庫的業務遷移至AnalyticDB PostgreSQL版的工作量。
存儲過程支持內部開啟事務塊,進行事務提交(Commit)或者事務回滾(Rollback),而函數無此功能,只能整體提交或回滾一個事務。
存儲過程無類似Function的返回值,但是可以通過output參數獲取返回結果。
示例
示例一
本示例中將創建一個存儲過程,對其中一個事務進行提交,另外一個事務進行回滾。
創建存儲過程,并在存儲過程中控制不同事務。
CREATE PROCEDURE proc() LANGUAGE plpgsql AS $$ BEGIN CREATE TABLE table_a (id int); INSERT INTO table_a VALUES(1); COMMIT; CREATE TABLE table_b (cid int); INSERT INTO table_b VALUES(1); ROLLBACK; END; $$;
調用存儲過程。
CALL proc();
查看存儲過程執行結果。
在psql中執行
\d
查看當前庫中的所有表,返回信息如下:List of relations Schema | Name | Type | Owner | Storage --------+---------+-------+------------+--------- public | table_a | table | adbpgadmin | heap (1 row)
查看表table_a:
SELECT * FROM table_a;
返回信息如下:
id ---- 1 (1 row)
通過上述存儲過程執行結果可以看到表
table_a
相關事務提交,成功建表并寫入數據;而表table_b
相關的事務在存儲過程中被回滾。
示例二
本示例將分別在存儲過程和函數中執行一個循環任務并回收表的存儲空間,以體現存儲過程和函數在提交事物方面的區別。
存儲過程提供了事務提交能力,您可以在存儲過程執行過程中對事務進行提交。以下示例,存儲過程可以實現在循環任務期間及時回收表空間:
CREATE PROCEDURE run_procedure() LANGUAGE plpgsql AS $$ BEGIN FOR i in 1..10 LOOP INSERT INTO t VALUES(i);-- 在表t上執行一系列任務,示例中為INSERT任務。 TRUNCATE t; COMMIT; -- 在循環內提交TRUNCATE任務,回收表t的物理存儲空間。 END LOOP; END; $$;
函數無法在執行過程中進行事務提交,僅能在函數執行完成后作為一個事務一次性提交。以下示例,函數無法在循環任務期間回收表空間:
CREATE FUNCTION run_function() RETURNS void LANGUAGE plpgsql AS $$ BEGIN FOR i in 1..10 LOOP INSERT INTO t VALUES(i);-- 在表t上執行一系列任務,示例中為INSERT任務。 TRUNCATE t; -- COMMIT; 不支持事務提交。 END LOOP; END; $$;