建立套件規格與主體,定義 REF CURSOR 類型供 JDBC 取得結果集。
CREATE OR REPLACE PACKAGE PKG_UIREPORT_DEPTTRANSTABLE AS
TYPE MY_CURSOR IS REF CURSOR;
PROCEDURE ZCCCGC(
NAME_OUT OUT MY_CURSOR,
V_COUNT OUT INT,
LIKES IN NVARCHAR2,
STARTS IN INT,
LIMITS IN INT
);
END;
/
CREATE OR REPLACE PACKAGE BODY PKG_UIREPORT_DEPTTRANSTABLE AS
PROCEDURE ZCCCGC(
NAME_OUT OUT MY_CURSOR,
V_COUNT OUT INT,
LIKES IN NVARCHAR2,
STARTS IN INT,
LIMITS IN INT
) IS
STR VARCHAR2(1000);
BEGIN
-- 範例:插入暫存表
INSERT INTO TTABLE ("NAME1","NAME2","NAME3")
SELECT "NAME11","NAME22","NAME3" FROM "TABLE";
-- 動態分頁查詢
STR := 'SELECT "NAME1","NAME2","NAME3" FROM (
SELECT ROW_.*, ROWNUM ROWNUM_
FROM (SELECT * FROM TTABLE ' || LIKES || ') ROW_
WHERE ROWNUM <= ' || LIMITS || ')
WHERE ROWNUM_ > ' || STARTS;
OPEN NAME_OUT FOR STR;
-- 總筆數
STR := 'SELECT COUNT(*) FROM TTABLE ' || LIKES;
EXECUTE IMMEDIATE STR INTO V_COUNT;
END ZCCCGC;
END;
/
import java.sql.*;
import oracle.jdbc.OracleTypes;
public class ProcedureTest {
public static void main(String[] args) {
String dbDriver = "oracle.jdbc.driver.OracleDriver";
String dbURL = "jdbc:oracle:thin:@localhost:1521:orcl";
String user = "hr";
String pass = "zaylqn";
try (Connection conn = DriverManager.getConnection(dbURL, user, pass)) {
conn.setAutoCommit(false);
// 對應 5 參數:OUT CURSOR, OUT INT, IN VARCHAR2, IN INT, IN INT
String sql = "{CALL PKG_UIREPORT_DEPTTRANSTABLE.ZCCCGC(?,?,?,?,?)}";
try (CallableStatement stmt = conn.prepareCall(sql)) {
stmt.registerOutParameter(1, OracleTypes.CURSOR);
stmt.registerOutParameter(2, OracleTypes.INTEGER);
stmt.setString(3, " WHERE LOWER(\"NAME2\") LIKE LOWER('%xx%')");
stmt.setInt(4, 0); // STARTS
stmt.setInt(5, 30); // LIMITS
stmt.execute();
int total = stmt.getInt(2);
System.out.println("總筆數:" + total);
try (ResultSet rs = (ResultSet) stmt.getObject(1)) {
while (rs.next()) {
System.out.println(rs.getString(1) + " | " + rs.getString(2));
System.out.println("----------------------------------------");
}
}
}
conn.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}
OracleTypes.CURSOREXECUTE IMMEDIATE 配合 OPEN ... FOR 實現靈活查詢registerOutParameter 索引從 1 開始,需與 PL/SQL 宣告順序完全一致Connection/CallableStatement/ResultSetROWNUM 雙層嵌套,相容 Oracle 11g 及以下版本| 錯誤現象 | 原因 | 解決 |
|---|---|---|
PLS-00306 參數數量/類型不符 | Java 與 PL/SQL 參數順序、類型不匹配 | 核對 registerOutParameter 類型與索引 |
ORA-01001 無效游標 | ResultSet 使用前已關閉 Statement | 在 stmt 關閉前讀取 ResultSet |
| 中文亂碼 | 資料庫/驅動程式字元集不一致 | 確認 NLS_LANG、JDBC URL 含 characterEncoding |