DB2 不像 MySQL 有 LIMIT offset, rows 或 Oracle 有 ROWNUM,其標準分頁方案結合 FETCH FIRST n ROWS ONLY 與 NOT IN (子查詢) 實現。本文提供完整的 Java/JDBC 參考實現,包含總記錄數統計、總頁數計算、當前頁邊界處理及動態 SQL 拼裝。
SELECT * FROM stu.book <條件> FETCH FIRST <pageSize> ROWS ONLY
SELECT * FROM stu.book <條件>
AND booknum NOT IN (
SELECT booknum FROM stu.book <條件> FETCH FIRST <(N-1)*pageSize> ROWS ONLY
)
FETCH FIRST <pageSize> ROWS ONLY
原理: 子查詢取出前 (N-1) 頁的主鍵,外層查詢排除這些主鍵,再取前 pageSize 條。
public List<Book> queryPage(String condition, String CPage) {
String sqlCount = "SELECT COUNT(*) FROM stu.book " + condition;
int pageSize = 10;
int curPage = 1;
// 1. 解析並校驗頁碼
if (CPage != null) {
try { curPage = Integer.parseInt(CPage); }
catch (NumberFormatException e) { curPage = 1; }
if (curPage < 1) curPage = 1;
}
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<Book> list = new ArrayList<>();
try {
con = Dao.getConn();
// 2. 查總記錄數
ps = con.prepareStatement(sqlCount);
rs = ps.executeQuery();
int totalRecords = 0;
if (rs.next()) totalRecords = rs.getInt(1);
// 3. 計算總頁數
int totalPages = (totalRecords + pageSize - 1) / pageSize;
if (curPage > totalPages) curPage = totalPages; // 防止越界
// 4. 構建分頁 SQL
String sql;
if (curPage == 1) {
sql = "SELECT * FROM stu.book " + condition + " FETCH FIRST " + pageSize + " ROWS ONLY";
} else {
int offset = (curPage - 1) * pageSize;
sql = "SELECT * FROM stu.book " + condition +
" AND booknum NOT IN (SELECT booknum FROM stu.book " + condition +
" FETCH FIRST " + offset + " ROWS ONLY) " +
" FETCH FIRST " + pageSize + " ROWS ONLY";
}
System.out.println("執行 SQL: " + sql);
// 5. 執行查詢並映射對象
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
Book b = new Book();
b.setBooknum(rs.getString(1));
b.setBookname(rs.getString(2));
b.setBookindate(rs.getString(3));
b.setBorrower(rs.getString(4));
b.setLenddate(rs.getString(5));
b.setRemark(rs.getString(6));
list.add(b);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 關閉資源 (省略具體 close 代碼)
}
return list;
}
booknum 為唯一主鍵,若無主鍵需組合唯一鍵。NOT IN 子查詢掃描量大,海量數據建議改用游標、臨時表或 ROW_NUMBER() OVER() 窗口函數(DB2 9.7+ 支持)。condition 變量需包含 WHERE 關鍵字(如 " WHERE status=1"),否則 SQL 語法錯誤。