问题
I am trying to call a PL/SQL
procedure which has defaults defined for some of its parameters. I am doing this using CallableStatement
in JDBC
.
This procedure has a large number of parameters with defaults defined. I do not want to explicitly set the defaults in the Java code. Doing this would make maintaining the code harder. If the PL/SQL code changes , would have to make the same changes in the Java code too.
Is it possible to accomplish this in JDBC ? For instance just bind values to the parameter you are interested in and ignore the rest.
I tried this on the following sample procedure :
-- PURPOSE: Takes a parameter which has defaults set. Returns the value of the same parameter
-- Example of: FUNCTION that takes a parameter with DEFAULT values
FUNCTION handle_defaults(empId IN NUMBER DEFAULT 20 , empCity IN VARCHAR2) RETURN NUMBER IS
BEGIN
RETURN empId;
EXCEPTION
WHEN others THEN
dbms_output.put_line('Error!');
END handle_defaults;
Here is the relevant portions of the code (NOTE: Have stripped off the try catch block , cleaning up of database resources etc for sake of readability)
// Create a database connection
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
// Create a query string
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
// Create a Callable Statements
callStmt = conn.prepareCall(queryStr);
// Bind values to the IN parameter
callStmt.setString(3, "Mumbai");
// Register OUT parameter
callStmt.registerOutParameter(1, java.sql.Types.NUMERIC);
// Execute the Callable Statement
callStmt.execute();
// Retrieve the value of the OUT parameter
parameterValue = callStmt.getInt(1);
System.out.println("Value returned : " + parameterValue);
I get the following error:
Exception occured in the database
java.sql.SQLException: Missing IN or OUT parameter at index:: 2
Database error code: 17041
As a desperate attempt I also tried to pass Nulls for those parameters. Just included the following line:
callStmt.setNull(2, java.sql.Types.NUMERIC);
I get the following result:
Value returned : 0
That makes sense bcoz setNull
supplies SQL Null to the parameter.
I am using Oracle 11g
and Oracle 12c Jdbc Driver Version 12.1.0.2
.
回答1:
I don't think there's a simple answer to this question, and that's not because of JDBC, but because of Oracle.
Put simply, the only way I know of calling a procedure and using the default value for a parameter is to not specify the parameter when you call the procedure.
If you are writing
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
you are always specifying both parameters, so you can never use the default value for one of them. If you only want to specify one of them and use the default for the other, write:
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( empCity => ? ) }";
In this case you need to specify the parameter name in the call, as the first parameter is the optional one. If the second parameter was optional instead, the parameter name can be dropped.
Unfortunately, this becomes quite complicated for your real procedure with lots of parameters. What I would do would be to:
- Use a StringBuilder to build up the procedure call string.
- Run through the parameters, adding
paramName => ?
parts to it for each parameter you have a value for. Ensure the parts are separated by commas. - Prepare a CallableStatement using the output of the StringBuilder.
- Run through the parameters again and call various
setString
/setInt
/setDate
/etc. methods on the CallableStatement for each parameter you have a value for.
来源:https://stackoverflow.com/questions/27433850/invoking-procedure-defaults-without-binding-values-to-parameters-in-jdbc