Oracle Function 要回傳「表」結果集,必須先定義 **物件型別** → **集合型別**,再在 Function 中構建集合回傳。本文提供兩種模式:PIPELINED 流式回傳**(記憶體效率高、支援並行)與**一般集合回傳**(簡單、小資料量)的完整範本。
CREATE OR REPLACE TYPE obj_table AS OBJECT (
id INT,
name VARCHAR2(50)
);
CREATE OR REPLACE TYPE t_table IS TABLE OF obj_table;
CREATE OR REPLACE FUNCTION f_pipe(p_cnt IN NUMBER)
RETURN t_table PIPELINED
AS
v_obj obj_table;
BEGIN
FOR i IN 1 .. p_cnt LOOP
v_obj := obj_table(i, TO_CHAR(i * i)); -- 建構物件實例
PIPE ROW(v_obj); -- 逐列流式輸出
END LOOP;
RETURN; -- PIPELINED 必須以空 RETURN 結束
END f_pipe;
/
-- 呼叫方式(TABLE() 轉換為關聯式結果集)
SELECT * FROM TABLE(f_pipe(5));
CREATE OR REPLACE FUNCTION f_normal(p_cnt IN NUMBER)
RETURN t_table
AS
v_rs t_table := t_table(); -- 必須初始化空集合
BEGIN
FOR i IN 1 .. p_cnt LOOP
v_rs.EXTEND; -- 擴展集合大小
v_rs(v_rs.COUNT) := obj_table(v_rs.COUNT, 'name' || v_rs.COUNT);
END LOOP;
RETURN v_rs;
END f_normal;
/
-- 呼叫方式
SELECT * FROM TABLE(f_normal(5));
| 特性 | PIPELINED | 一般集合 |
|---|---|---|
| 記憶體佔用 | 流式,逐列產生,**O(1)** | 一次構建整個集合,**O(N)** |
| 並行查詢 | 支援 PARALLEL_ENABLE | 不支援 |
| 轉換開銷 | 無中間集合分配 | 需分配完整集合記憶體 |
| 適用場景 | ETL、大量資料轉換、資料泵 | 小筆資料、快速原型、單元測試 |
| RETURN 語法 | 空 RETURN; | RETURN collection_var; |
若需在多個 Function/Procedure 間共享「表變數」,可用 DBMS_SESSION.SET_CONTEXT 搭配 SYS_CONTEXT 實現命名空間變數:
-- 建立 Context 命名空間(需 CREATE ANY CONTEXT 權限)
CREATE OR REPLACE CONTEXT my_ctx USING pkg_ctx;
-- 套件 pkg_ctx 內設定/讀取
DBMS_SESSION.SET_CONTEXT('my_ctx', 'my_table', serialized_collection);
val := SYS_CONTEXT('my_ctx', 'my_table');
CallableStatement cs = conn.prepareCall("{? = call f_pipe(?)}");
cs.registerOutParameter(1, OracleTypes.CURSOR); -- PIPELINED 實際回傳 CURSOR
cs.setInt(2, 100);
cs.execute();
ResultSet rs = (ResultSet) cs.getObject(1);
while (rs.next()) { ... }
回傳表類型是 Oracle PL/SQL 模組化、資料轉換封裝的核心技術。**PIPELINED + 物件型別 + 集合型別** 是企業級開發標準模式。