openGauss 關於 PL/SQL 匿名塊呼叫測試
一、原理介紹
PL/SQL(Procedure Language/Structure Query Language)是標準 SQL 語言新增了過程化功能的一門程式設計語言。
單一的 SQL 語句只能進行資料操作,沒有流程控制,無法開發複雜的應用。PL/SQL 語言是結合了結構化查詢與資料庫自身過程控制為一體的強大語言。
1.PL/SQL 原理
PL/SQL 是一種塊結構的語言,它將一組語句放在一個塊中,一次性傳送給伺服器。
PL/SQL 引擎分析收到 PL/SQL 語句塊中的內容,把其中的過程控制語句由 PL/SQL 引擎自身去執行,把 PL/SQL 塊中的 SQL 語句交給伺服器的 SQL 語句執行器執行。
PL/SQL 塊傳送給伺服器後,先被編譯然後執行,對於有名稱的 PL/SQL 塊(如子程式)可以單獨編譯,永久的儲存在資料庫中,隨時準備執行。
PL/SQL 是一種塊結構的語言,一個 PL/SQL 程式包含了一個或者多個邏輯塊,邏輯塊中可以宣告變數,變數在使用之前必須先宣告。
2.PL/SQL 特點
–與 SQL 緊密結合 –支援物件導向程式設計 –更好的效能 –可移植性 –安全性
3.語法結構
除了正常的執行程式外,PL/SQL 還提供了專門的異常處理部分進行異常處理
[DECLARE
--declaration statements] ①
BEGIN
--executable statements ②
[EXCEPTION
--exception statements] ③
END;
語法解析 ① 宣告部分:宣告部分包含了變數和常量的定義。在此宣告 PL/SQL 用到的變數,型別及遊標,以及區域性的儲存過程和函式, 這個部分由關鍵字 DECLARE 開始,如果不宣告變數或者常量,可以省略這部分。 ② 執行部分:執行部分是 PL/SQL 塊的指令部分,由關鍵字 BEGIN 開始,關鍵字 END 結尾。 所有的可執行 PL/SQL 語句都放在這一部分,該部分執行命令並操作變數。其他的 PL/SQL 塊可以作為子塊巢狀在該部分。 PL/SQL 塊的執行部分是必選的。注意 END 關鍵字後面用分號結尾。 ③ 異常處理部分:該部分是可選的,該部分用 EXCEPTION 關鍵字把可執行部分分成兩個小部分,之前的程式是正常執行的程式, 一旦出現異常就跳轉到異常部分執行。
4.PL/SQL 語句塊的型別
1、匿名塊 2、命名塊 –①procedure 儲存過程 –②function 函式 –③package 包 –④trigger 觸發器
原本大家可能一提到 PL/SQL 就會想到 ORACLE,ORACLE 的 PL/SQL 很強大,它的匿名塊呼叫以及有名塊呼叫可以解決很多問題,在 openGauss 中,其實也有這樣的功能,如下,是我針對 openGauss 匿名塊的一些測試。
二、匿名塊測試
1.普通匿名塊呼叫
openGauss=# create table t1(a int ,b text);
CREATE TABLE
openGauss=# DECLARE
openGauss-# PRAGMA AUTONOMOUS_TRANSACTION;
openGauss-# BEGIN
openGauss$# raise notice 'Normal anonymous block printing.';
openGauss$# insert into t1 values(1,'I am lmj!');
openGauss$# END;
openGauss$# /
NOTICE: Normal anonymous block printing.
ANONYMOUS BLOCK EXECUTE
openGauss=# select * from t1;
a | b
---+-----------
1 | I am lmj!
(1 row)
2.匿名塊和事務影響
啟動一個事務後,執行一個自治事務匿名塊,如果事務回滾,則匿名塊不回滾。
3.外部匿名塊和內部匿名塊
其中外部匿名塊是一個公共匿名塊,而內部匿名塊是一個自治事務匿名塊,可以根據如下例子和第二個例子對比事務回滾和匿名塊回滾
openGauss=# truncate table t1;
TRUNCATE TABLE
openGauss=# START TRANSACTION;
START TRANSACTION
openGauss=# DECLARE
openGauss-# PRAGMA AUTONOMOUS_TRANSACTION;
openGauss-# BEGIN
openGauss$# raise notice 'an autonomous transaction anonymous block.';
openGauss$# insert into t1 values(1,'it will commit!');
openGauss$# END;
openGauss$# /
NOTICE: an autonomous transaction anonymous block.
ANONYMOUS BLOCK EXECUTE
openGauss=# insert into t1 values(1,'you will rollback!');
INSERT 0 1
openGauss=# rollback;
ROLLBACK
openGauss=# select * from t1;
a | b
---+-----------------
1 | it will commit!
(1 row)
4.匿名塊直接執行自治事務匿名塊並引發異常
openGauss=# DECLARE
openGauss-# PRAGMA AUTONOMOUS_TRANSACTION;
openGauss-# res int := 0;
openGauss-# res2 int := 1;
openGauss-# BEGIN
openGauss$# raise notice 'just use call.';
openGauss$# res2 = res2/res;
openGauss$# END;
openGauss$# /
NOTICE: just use call.
ERROR: ERROR: division by zero
CONTEXT: PL/pgSQL function inline_code_block line 7 at assignment
匿名塊執行錯誤,會報出異常
5.異常捕獲
在執行期間引發異常後,將捕獲匿名塊,如下所示,在執行錯誤後,丟擲 autonomous throw exception 提示
openGauss=# DECLARE
openGauss-# PRAGMA AUTONOMOUS_TRANSACTION;
openGauss-# res int := 0;
openGauss-# res2 int := 1;
openGauss-# BEGIN
openGauss$# raise notice 'error catch.';
openGauss$# res2 = res2/res;
openGauss$# EXCEPTION
openGauss$# WHEN division_by_zero THEN
openGauss$# raise notice 'autonomous throw exception.';
openGauss$# END;
openGauss$# /
NOTICE: error catch.
NOTICE: autonomous throw exception.
ANONYMOUS BLOCK EXECUTE