PL/SQL (Procedural Language/SQL) 是 Oracle 將程式邏輯 (條件、迴圈、例外處理) 與 SQL 深度整合的擴展語言。它運行於資料庫核心引擎,支援存儲程序、函數、觸發器、套件,實現業務邏輯下沉、網路往返減少、安全性封裝三大核心價值。
| 優勢 | 說明 |
|---|---|
| 緊密整合 SQL | 支援 DML、DDL、TCL、游標、SQL 函數/運算符,無縫嵌入 |
| 高效能 | 批次處理 (FORALL/BULK COLLECT)、減少網路往返、編譯後原生執行 |
| 可移植性 | 相容所有支援 Oracle 的 OS/平台 |
| 物件導向 | 支援 ADT、集合、繼承、多型 |
| 安全性 | 透過存儲程序控制資料存取、定義者/調用者權限模型 |
| 健壯例外處理 | 預定義/自訂例外、SAVEPOINT/ROLLBACK 精細交易控制 |
[DECLARE
-- 宣告區:變數、常數、游標、自訂型別、例外
v_salary NUMBER(8,2) := 0;
c_tax_rate CONSTANT NUMBER := 0.05;
CURSOR c_emp IS SELECT * FROM employees;
e_salary_too_high EXCEPTION;
BEGIN
-- 可執行區 (必須):業務邏輯、SQL、流程控制
SELECT salary INTO v_salary FROM employees WHERE employee_id = 100;
IF v_salary > 20000 THEN
RAISE e_salary_too_high;
END IF;
UPDATE employees SET salary = salary * 1.1 WHERE employee_id = 100;
COMMIT;
EXCEPTION
-- 例外處理區 (可選)
WHEN e_salary_too_high THEN
DBMS_OUTPUT.PUT_LINE('薪資超標: ' || SQLERRM);
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('查無員工');
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('系統錯誤: ' || SQLCODE || ' - ' || SQLERRM);
END;
-- 語法
identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr];
-- 範例
v_emp_id employees.employee_id%TYPE; -- 錨定型別
v_emp_rec employees%ROWTYPE; -- 記錄型別
c_pi CONSTANT NUMBER := 3.14159;
v_hiredate DATE DEFAULT SYSDATE;
v_flag BOOLEAN := TRUE;
賦值方式::= 直接賦值 / SELECT ... INTO 查詢賦值
| 分類 | 類型 | 說明 |
|---|---|---|
| 純量 | NUMBER(p,s) | 數值,精度 38 位 |
| VARCHAR2(n) | 變長字串,最大 32767 (PL/SQL) / 4000 (SQL) | |
| CHAR(n) | 定長字串,右補空白 | |
| DATE | 日期時間,精度至秒 | |
| TIMESTAMP | 高精度時間戳,含微秒/時區 | |
| BOOLEAN | 邏輯值 TRUE/FALSE/NULL,僅 PL/SQL 可用 | |
| LOB | CLOB | 字元大物件,最大 4GB |
| BLOB | 二進位大物件 | |
| NCLOB | Unicode 字元大物件 | |
| BFILE | 外部檔案定位器 (唯讀) | |
| LONG/LONG RAW | 已棄用,請改用 LOB | |
| 複合 | RECORD | 異質欄位群組 |
| COLLECTION | 關聯陣列、巢狀表、VARRAY | |
| REF CURSOR | 游標變數,動態查詢結果集 | |
DECLARE
v_clob CLOB;
v_buffer VARCHAR2(32767);
v_amount INTEGER := 1000;
v_offset INTEGER := 1;
BEGIN
SELECT content INTO v_clob FROM documents WHERE doc_id = 100;
LOOP
DBMS_LOB.READ(v_clob, v_amount, v_offset, v_buffer);
DBMS_OUTPUT.PUT_LINE(v_buffer);
v_offset := v_offset + v_amount;
EXIT WHEN v_offset > DBMS_LOB.GETLENGTH(v_clob);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('查無文件');
END;
| 特性 | 關聯陣列 | 巢狀表 | VARRAY |
|---|---|---|---|
| 索引類型 | PLS_INTEGER/VARCHAR2 | 正整數 | 正整數 |
| 大小 | 無上限 | 無上限 | 固定上限 |
| 稀疏性 | 支援 | 支援 (DELETE 後) | 不支援 (稠密) |
| 可存資料庫 | 否 | 是 | 是 |
| 適用場景 | 記憶體快取、查找表 | 資料庫欄位、大量資料 | 有序小集合、固定上限 |
SHOW ERRORS / SELECT * FROM USER_ERRORS 檢視編譯錯誤DBMS_OUTPUT.PUT_LINE 除錯輸出,記得 SET SERVEROUTPUT ONPL/SQL Debugger (SQL Developer / TOAD) 斷點單步追蹤PLSQL_OPTIMIZE_LEVEL=2 (預設) 享受編譯器優化掌握 PL/SQL 區塊結構、資料類型選擇、集合操作與例外處理模式,是開發高效能、可維護 Oracle 應用的關鍵基石。