分頁查詢是企業級應用的高頻需求。本文提供一套通用的 Oracle 分頁存儲過程封裝方案,支援動態表名、欄位、頁面大小與當前頁參數,並同步返回總頁數與結果游標,適配 Java 等應用層直連調用。
採用雙層嵌套 ROWNUM 方案:內層截取前 N 條,外層過濾起始行號。同時動態執行 COUNT(*) 獲取總記錄數,計算總頁數。代碼結構清晰,參數化程度高,可直接集成至通用 DAO 層。
CREATE OR REPLACE PACKAGE MAHANPACK AS
TYPE my_cursor IS REF CURSOR;
END MAHANPACK;
CREATE OR REPLACE PACKAGE BODY PAGEUTIL IS
PROCEDURE getResults(
tableName IN VARCHAR2,
colsStr IN VARCHAR2,
pageSize IN NUMBER,
currentPage IN NUMBER,
pageCount OUT NUMBER,
p_cursor OUT MAHANPACK.my_cursor
) IS
v_sql VARCHAR2(2000);
v_begin NUMBER := (currentPage - 1) * pageSize + 1;
v_end NUMBER := currentPage * pageSize;
BEGIN
-- 分頁查詢
v_sql := 'SELECT * FROM (SELECT t.*, ROWNUM rn FROM (SELECT ' || colsStr || ' FROM ' || tableName || ') t WHERE ROWNUM <= ' || v_end || ') WHERE rn >= ' || v_begin;
OPEN p_cursor FOR v_sql;
-- 總記錄數與總頁數
v_sql := 'SELECT COUNT(*) FROM ' || tableName;
EXECUTE IMMEDIATE v_sql INTO pageCount;
IF MOD(pageCount, pageSize) = 0 THEN
pageCount := pageCount / pageSize;
ELSE
pageCount := pageCount / pageSize + 1;
END IF;
END;
END PAGEUTIL;
BEGIN
PAGEUTIL.getResults(
tableName => 'emp',
colsStr => 'empno, ename',
pageSize => 20,
currentPage=> 1,
pageCount => :count,
p_cursor => :c1
);
END;
/
PRINT count;
PRINT c1;
輸出結果顯示總頁數 1.7(即 2 頁),首頁返回 14 筆員工記錄,含 ROWNUM 欄位,驗證邏輯正確。生產環境建議增加 SQL 注入防護、異常處理與統計信息緩存機制,進一步提升穩定性與效能。