標量參數 (NUMBER/VARCHAR2) 單值回傳,無法滿足批量資料回傳、二維結果集、複雜統計報表 需求。PL/SQL 三大集合類型提供陣列/集合操作能力。
| 特性 | 索引表 | VARRAY (可變陣列) | 巢狀表 |
|---|---|---|---|
| 定義位置 | 僅 PL/SQL 區塊或 Package Spec | SQL 層級 (`CREATE TYPE`) | SQL 層級 (`CREATE TYPE`) |
| 大小限制 | 無上限 (受 BINARY_INTEGER 限制) | **宣告時固定上限** (可 EXTEND 但不超過) | 無上限 |
| 儲存特性 | 稀疏、非連續、雜湊表結構 | **連續記憶體**、緊湊 | 稀疏、可儲存於資料庫欄位 |
| 初始化 | **自動**,直接指派值 | **必須建構器初始化** `TYPE_NAME()` | **必須建構器初始化** `TYPE_NAME()` |
| 索引起始 | 任意整數 (負數也可) | **固定從 1 開始**、連續 | 固定從 1 開始、連續 (但可 DELETE 造成稀疏) |
| SQL 操作 | **不支援** (無法 SELECT * FROM TABLE(idx_tab)) | 支援 `TABLE()` 轉換 | **完整支援** `SELECT * FROM TABLE(nested_tab)` |
| 持久化 | 僅 Session 記憶體,不可存資料庫 | 可做為欄位型別儲存 | 可做為欄位型別儲存 |
| 驅動支援 | 需 OCI 驅動 (JDBC OCI) | JDBC Thin/OCI 均支援 | JDBC Thin/OCI 均支援 (透過 REF CURSOR) |
| 回傳方式 | OUT 參數直接回傳集合 | OUT 參數或 FUNCTION RETURN | **轉換為 REF CURSOR 回傳** |
-- Package 定義 (必須在 Package Spec)
CREATE OR REPLACE PACKAGE pkg_demo AS
TYPE idx_tab_t IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
PROCEDURE get_names(p_deptno IN NUMBER, p_names OUT idx_tab_t);
END pkg_demo;
/
CREATE OR REPLACE PACKAGE BODY pkg_demo AS
PROCEDURE get_names(p_deptno IN NUMBER, p_names OUT idx_tab_t) IS
CURSOR c IS SELECT ename FROM emp WHERE deptno = p_deptno;
v_idx BINARY_INTEGER := 1;
BEGIN
FOR r IN c LOOP
p_names(v_idx) := r.ename; -- 自動擴展,無需 EXTEND
v_idx := v_idx + 1;
END LOOP;
END;
END pkg_demo;
/
-- SQL 層級建立型別
CREATE OR REPLACE TYPE num_varray IS VARRAY(10) OF NUMBER(3);
/
-- Function 回傳
CREATE OR REPLACE FUNCTION get_seq RETURN num_varray IS
v_arr num_varray := num_varray(); -- 必須初始化
BEGIN
FOR i IN 1..5 LOOP
v_arr.EXTEND;
v_arr(i) := i * 10;
END LOOP;
RETURN v_arr;
END;
/
-- Java 端直接映射為 int[] 或 Array
-- 1. 物件型別 (對應結果集欄位)
CREATE OR REPLACE TYPE stat_obj AS OBJECT (
dept_name VARCHAR2(30),
emp_count NUMBER,
avg_sal NUMBER,
max_sal NUMBER
);
/
-- 2. 巢狀表型別
CREATE OR REPLACE TYPE stat_tab IS TABLE OF stat_obj;
/
-- 3. Package 定義 REF CURSOR
CREATE OR REPLACE PACKAGE pkg_report AS
TYPE ref_cur IS REF CURSOR;
PROCEDURE dept_stats(p_cur OUT ref_cur);
END pkg_report;
/
-- 4. 實作:填充巢狀表 -> CAST -> OPEN CURSOR
CREATE OR REPLACE PACKAGE BODY pkg_report AS
PROCEDURE dept_stats(p_cur OUT ref_cur) IS
v_tab stat_tab := stat_tab(); -- 初始化
BEGIN
-- 模擬查詢填充
v_tab.EXTEND;
v_tab(1) := stat_obj('SALES', 10, 2500, 5000);
v_tab.EXTEND;
v_tab(2) := stat_obj('IT', 5, 4000, 8000);
-- 關鍵:CAST 巢狀表為 SQL 集合 -> 開啟游標
OPEN p_cur FOR SELECT * FROM TABLE(CAST(v_tab AS stat_tab));
END;
END pkg_report;
/