SQL 是宣告式的「說什麼」,PL/SQL 是過程式的「怎麼做」。Oracle PL/SQL 將 SQL 嵌入程式邏輯,賦予開發者實現複雜業務規則、批量處理、事件驅動的能力。本文系統梳理 PL/SQL 核心知識體系:程式結構、控制流、變數與資料型別、SQL 整合、程序/函數、游標、包與觸發器,為進階開發鋪路。
所有 PL/SQL 程式碼皆以 Block 為單位,三段式結構:
DECLARE -- 宣告區 (可選)
變數、游標、例外、子程式...
BEGIN -- 執行區 (必須)
可執行陳述式...
EXCEPTION -- 例外處理區 (可選)
WHEN exception_name THEN ...
END;
巢狀 Block 可構建模組化邏輯,內層 Block 可捕獲外層未處理的例外,實現細粒度錯誤控制。
支援多條件分支,無 Switch/Case 陳述式(可用 CASE 運算式在 SQL/賦值中實現)。
LOOP ... EXIT WHEN ... END LOOP; 至少執行一次。WHILE condition LOOP ... END LOOP; 先判斷。FOR i IN [REVERSE] low..high LOOP ... END LOOP; 計數器隱式宣告、自動遞增/遞減、不可在迴圈中修改計數器。支援 GOTO label,但強烈不建議使用,結構化程式設計原則下,迴圈/條件/模組化足以替代,濫用導致義大利麵代碼。
語法: variable_name datatype [NOT NULL := default_value];
v_id NUMBER;。:=,非 =(= 僅用於 SQL 比較或預設值)。例:v_id := 5;。NUMBER(p,s)、VARCHAR2(size)、BOOLEAN、DATE、%TYPE、%ROWTYPE、RECORD、TABLE/VARRAY(集合)。PL/SQL 區塊可直接嵌入 DML (INSERT/UPDATE/DELETE)、SELECT INTO(單行)、COMMIT/ROLLBACK/SAVEPOINT (TCL)。DDL 需用動態 SQL (EXECUTE IMMEDIATE / DBMS_SQL)。
隱式游標屬性: SQL%ROWCOUNT、SQL%FOUND、SQL%NOTFOUND、SQL%ISOPEN 即時反映最近一條 DML/SELECT INTO 影響。
| 特性 | Procedure | Function |
|---|---|---|
| 返回值 | 無 (可用 OUT/IN OUT 參數回傳多值) | 必須有 RETURN 型別,單一值 |
| 呼叫方式 | 獨立陳述式 proc(...); | 表達式一部分 v := func(...); |
| SQL 中呼叫 | 不可直接用於 SQL | 可用於 SQL (需 DETERMINISTIC/無副作用) |
| 建立語法 | CREATE OR REPLACE PROCEDURE name(params) AS ... | CREATE OR REPLACE FUNCTION name(params) RETURN type AS ... |
參數模式:IN (預設,唯讀)、OUT (唯寫,回傳)、IN OUT (雙向)。預設值僅限 IN 參數。
SELECT INTO、DML 自動開啟,僅支援單行結果,多行拋 TOO_MANY_ROWS。
CURSOR c_emp IS SELECT * FROM emp WHERE deptno = p_deptno;
-- 參數化游標
CURSOR c_emp(p_deptno NUMBER) IS SELECT * FROM emp WHERE deptno = p_deptno;
生命週期: OPEN → FETCH INTO (迴圈) → CLOSE。
屬性: %FOUND、%NOTFOUND、%ROWCOUNT、%ISOPEN。
FOR 迴圈游標: FOR rec IN c_emp LOOP ... END LOOP; 自動 OPEN/FETCH/CLOSE,最簡潔推薦。
用於程式間傳遞結果集、動態構建查詢、回傳給客戶端 (JDBC/ODP.NET)。
TYPE t_refcur IS REF CURSOR; (強類型) 或 SYS_REFCURSOR (弱類型)。
包規格 (Spec) : 公開介面(程序/函數/變數/游標/型別/例外宣告)。
包主體 (Body) : 實作細節、私有元素、初始化區塊。
核心價值:
GRANT EXECUTE ON pkg TO user; 粒度精細。BEFORE/AFTER INSERT/UPDATE/DELETE)、DDL、Database Event (STARTUP/SHUTDOWN/LOGON/LOGOFF)、INSTEAD OF (View)。%TYPE/%ROWTYPE 錨定型別,結構變更自動適應。BULK COLLECT + FORALL,減少 Context Switch。WHEN OTHERS THEN LOG + RAISE;,不可吞沒錯誤。DETERMINISTIC、RESULT_CACHE、PARALLEL_ENABLE 提升效能。FOR rec IN cursor LOOP。PL/SQL 是 Oracle 開發者的利劍。精通塊結構、控制流、游標機制、包設計哲學,配合 SQL 集合思維,才能寫出高效、可維護、可擴展的資料庫端業務邏輯。從今天開始,刻意練習每一個語法細節,內化為肌肉記憶。