EDIT
Putting this here in case it helps others. My problem was a failure in understanding how PreparedStatement works. I had believed that the "?"...setInt() syntax was a simple substitution that constructs an SQL statement, interprets it and sends that to the DB, which is not the case. The answers below explain in detail the problem.
ORIGINAL QUESTION
I'm having some trouble getting an Oracle package function call to execute from within a Java app. I am receiving the below error:
ORA-01858: a non-numeric character was found where a numeric was expected
I believe I have constructed the call correctly, and the only place I'm using a string is for a date field (not a numeric one). The function has the signature:
function f_get_mr_target(a_plan_id number,a_machine number,a_shift_id number,a_shift_dt date) return number;
My java code invoking the function is as follows:
public Double checkMRTarget(int planId, int machineNum, int shiftId, String date)
{
//Instantiate the return value
Double mrTarget = null;
//Get the MR target
try
{
//Ready the connection
con = nativeDataSource.getConnection();
//The query string
String sql = "select pkg_bcs.f_get_mr_target(?,?,?,?) target from dual";
//Prepare the query
stmt = null;
stmt = con.prepareStatement(sql);
stmt.setInt(1, planId);
stmt.setInt(2, machineNum);
stmt.setInt(3, shiftId);
stmt.setString(4, date);
//Execute the query
ResultSet rs = stmt.executeQuery();
//Extract the value from the result set
mrTarget = rs.getDouble("target");
}
catch (Throwable e)
{
System.out.println("Error getting mrTarget: " + e);
}
finally
{ closeDBConnections(); }
//Return the value
return mrTarget;
}
Con is a public Connection object shared by all other methods in the class. Stmt is a PreparedStatement object, also shared. The parameters are passed as follows:
planId = 986548
machineNum = 5227
shiftId = 10
date = "trunc(sysdate)"
I've verified that running
select pkg_bcs.f_get_mr_target(986548, 5227, 10, trunc(sysdate)) target from dual;
works just fine in SQLDeveloper. As far as I can tell, it's getting a number where it expects a number
trunc(sysdate)to a parameter that expects aDatetype? Parameter substitution is strongly typed, you cannot just pass arbitrary SQL text for aDateparameter.