本文詳細示範如何使用 Java 透過 JDBC 呼叫 Oracle 預存程序,涵蓋無回傳值、有回傳值(非列表)、回傳游標列表三大類型,提供完整 SQL 建立腳本與 Java 程式碼範例,並說明關鍵注意事項。
CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2, PARA2 IN VARCHAR2) AS
BEGIN
INSERT INTO T_TEST (I_ID, I_NAME) VALUES (PARA1, PARA2);
END TESTA;
import java.sql.*;
import oracle.jdbc.driver.*;
public class TestProcedureOne {
public static void main(String[] args) {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Connection conn = null;
CallableStatement proc = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, "dbname", "passWord");
proc = conn.prepareCall("{ call dbname.TESTA(?,?) }");
proc.setString(1, "100");
proc.setString(2, "TestOne");
proc.execute();
} catch (SQLException | Exception ex) {
ex.printStackTrace();
} finally {
// 關閉資源:proc, conn
}
}
}
CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2, PARA2 OUT VARCHAR2) AS
BEGIN
SELECT I_NAME INTO PARA2 FROM TESTTB WHERE I_ID = PARA1;
END TESTB;
public class TestProcedureTwo {
public static void main(String[] args) {
// ... 連線設定同前 ...
CallableStatement proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }");
proc.setString(1, "100");
proc.registerOutParameter(2, Types.VARCHAR); // 註冊 OUT 參數型別
proc.execute();
String result = proc.getString(2); // 索引對應 OUT 參數位置
System.out.println("Result: " + result);
}
}
關鍵提醒: `proc.getString(2)` 中的索引 2 對應預存程序中第二個參數(OUT 參數位置),若 OUT 參數在第一位則用 1,第三位用 3,多個 OUT 參數依序類推。
Oracle 預存程序無直接回傳值,列表回傳需透過 Package 定義 REF CURSOR 作為 OUT 參數。
CREATE OR REPLACE PACKAGE TESTPACKAGE AS
TYPE Test_CURSOR IS REF CURSOR;
PROCEDURE TESTC(cur_ref OUT Test_CURSOR);
END TESTPACKAGE;
CREATE OR REPLACE PACKAGE BODY TESTPACKAGE AS
PROCEDURE TESTC(cur_ref OUT Test_CURSOR) IS
BEGIN
OPEN cur_ref FOR SELECT * FROM T_TEST;
END TESTC;
END TESTPACKAGE;
CallableStatement proc = conn.prepareCall("{ call TESTPACKAGE.TESTC(?) }");
proc.registerOutParameter(1, OracleTypes.CURSOR); // 註冊游標型別
proc.execute();
ResultSet rs = (ResultSet) proc.getObject(1); // 取得 ResultSet
while (rs.next()) {
// 處理每一列資料
}