I have a PL/SQL stored function which returns a table of integers:
CREATE TYPE INT_TABLE IS TABLE OF INTEGER;
CREATE FUNCTION f (someParam IN INTEGER) RETURN INT_TABLE IS ...
I wish to use JDBC to retrieve the result of this function so that I can iterate through the integers in some way, be it a ResultSet
, int[]
, or whatever.
The function f
performs modifications to the database, so it cannot be called in a query such as SELECT f(42) FROM DUAL;
. The return value exists to inform the caller of the primary keys for the rows that it modified. I presumably must use a CallableStatement
, but can't figure out exactly how. Taking inspiration from here , I have tried:
CallableStatement cs = conn.prepareCall("{? = call f(42)}");
cs.registerOutParameter(1, Types.ARRAY);
cs.execute();
ResultSet rs = cs.getArray(1).getResultSet();
However, this resulted in java.sql.SQLException: Invalid argument(s) in call
on the registerOutParameter
line. I haven't been able to determine what this error actually means, as the docs are quite general on the exceptions that may be thrown.
I've spent hours googling and am at quite a loss as to how to proceed. Is it possible to extract a table type into Java? If not, is there some other way of returning multiple integers from the PL/SQL function that can be extracted into Java?
I'm answering my own question after figuring it out.
I was very close to the solution; I'd just missed specifying the type name in the registerOutParameter
call. The final solution therefore looks like:
cs = conn.prepareCall("{? = call f(42)}");
cs.registerOutParameter(1, Types.ARRAY, "INT_TABLE");
cs.execute();
ResultSet rs = cs.getArray(1).getResultSet();
This is native JDBC and does not require any of the Oracle extensions.
One other thing that tripped me up was the structure of this ResultSet
. It contains two columns; the first is the index and the second is the value ( documentation link ). Therefore, if you want to extract the elements of the array, you need to call rs.getInt(2)
for each row rather than rs.getInt(1)
.
If one instead wanted the result as a plain array rather than a ResultSet, the corresponding type is java.math.BigDecimal
, so it would be
...
cs.execute();
BigDecimal[] array = (BigDecimal[])(cs.getArray(1).getArray());
Yes, from oracle can return table of integer or others types. I think, you need define oracle type
On order: 1.create type and function
CREATE TYPE array_int IS TABLE OF INTEGER;
CREATE OR REPLACE FUNCTION get_array (v_id IN INTEGER)
RETURN array_int
IS
res array_int := array_int(1,2,3,4);
begin
return res;
end;
AND Java
ArrayList r_list = new ArrayList();
ArrayDescriptor arrayInt = ArrayDescriptor.createDescriptor("ARRAY_INT", con); //to oracle type
ARRAY iarray = new ARRAY(arrayInt, con, r_list.toArray());
OracleCallableStatement cst = (OracleCallableStatement) con.prepareCall(
"{call ?:= get_array(?)");
cst.registerOutParameter(1, OracleTypes.ARRAY, "ARRAY_INT");
cst.setInt(2, 1);
cst.execute();
iarray = cst.getARRAY(1);
cst.close();
Object[] pObjects = (Object[]) iarray.getArray();
for (int i = 0; i < pObjects.length; i++) {
System.out.print(pObjects[i]);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.