How do I retrieve the return value from a stored function call in groovy? - oracle

I am trying to make a call to a stored function in Oracle. This function not only has a return value but also has an OUT parameter. I am relatively new to Groovy but have a lot of database experience. How do I retrieve the actual values returned. Here is my sample call...assume I already have a good database connection.
I have a store function with the following signature:
GET_JOB(job_id IN VARCHAR2, max_sal OUT INTEGER) RETURNS VARCHAR2
I make the call in groovy:
def result = sql.call("{? = call get_job(?, ?)}", [Sql.VARCHAR, 'TE', Sql.NUMERIC])
This seems to run with no errors, but I am unclear as to how to retrieve the return value and the OUT parameter (second parameter)

The int Sql.call(String, List) form of the method doesn't handle output parameters. You can use void Sql.call(String, List, Closure) instead.
sql.call("{? = call get_job(?, ?)}", [Sql.VARCHAR, 'TE', Sql.NUMERIC]) { maxSal ->
// do whatever with maxSal
}
Note: If you get the return value of the stored procedure instead of the out parameter, try: sql.call(...) { ret, maxSal -> }

Related

PLSQL stored procedure query(toplink) returns bigdecimal fields without fraction

I call the stored procedure from Java (Toplink) as follows:
PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall();
call.setProcedureName("PACK_PORTAL_VIEW.get_payment_details");
call.addNamedArgument("p_order_id", JDBCTypes.NUMERIC_TYPE);
call.addNamedOutputArgument("some_variable", JDBCTypes.NUMERIC_TYPE);
DataReadQuery drQuery = new DataReadQuery();
drQuery.setCall(call);
drQuery.addArgument("p_order_id");
Query query = ((JpaEntityManager) em.getDelegate()).createQuery(drQuery);
query.setParameter("p_order_id", orderId);
DatabaseRecord record = (DatabaseRecord) query.getSingleResult();
record.get("some_variable");
record.get("some_variable") returns some value that is stored in the DB with a fractional part, but in java it is written without it
record.get("some_variable").getClass() returns BigDecimal.class
How can I get the fractional value stored in the database?
It was necessary to use the following method:
/**
* PUBLIC: Add a named OUT argument to the stored procedure. The databaseType parameter
* classifies the parameter (JDBCType vs. OraclePLSQLType, simple vs. complex). The extra scale
* and precision parameters indicates that this parameter, when used in an Anonymous PL/SQL
* block, requires scale and precision specification
*/
public void addNamedOutputArgument(String procedureParameterName, DatabaseType databaseType,
int precision, int scale) {
DatabaseType dt = databaseType.isComplexDatabaseType() ?
((ComplexDatabaseType)databaseType).clone() : databaseType;
arguments.add(new PLSQLargument(procedureParameterName, originalIndex++, OUT, dt,
precision, scale));
}

Debugging runtime pl/sql errors

I’m new in pl/sq.
So, I’m trying to call pl/sql stored procedure from Java, but appears error:
wrong number or types of arguments in call to ‘searchuser’.
Where can I find most specific exception?
Is there some error logs or errors table in oracle? How can I debug these kind of problems?
Thanks!
one thing is if you call stored procedures from java: don't forget to register the function result. Example Java code:
CallableStatement cstmt = connection.prepareCall("{? = call xxx.checkArea(?,?)}");
// the 1st Parameter is the result of the function checkArea
cstmt.registerOutParameter(1, Types.INTEGER); // Function Return
cstmt.setInt(2, status); // Parameter 1 (in)
cstmt.registerOutParameter(3, Types.INTEGER); // Parameter 2 (out)
// execute the call
cstmt.execute();
// check the results
sessionId = cstmt.getInt(1); // Session-ID
rows = cstmt.getInt(3); // Rows
The PL/SQL Function is declared as following:
function checkArea(pi_area in number,
po_rows out number) return number;

how to call oracle stored procedure in jpa2.0 which returns integer as out variable

I have written one stored procedure which will return integer value. but am not able to get the count in jpa. can any one suggest me the way to call stored procedure and get the return out value into some variable in java using jpa.
int count = 0;
String id = "m123"
count = getEm().createNativeQuery("call sample_procedure(?,?)")
.setParameter(1, id)
.setParameter(2, count)
.executeUpdate();
stored procedure: I have some logic in procedure and inside loop I was incrementing the count.
create or replace
PROCEDURE sample_procedure(
id IN VARCHAR,
count OUT NUMBER)
IS
........
BEGIN
.....
LOOP
---------
count := count + 1;
Looks similar to this answer
Options which I tried:
Tried with curly braces before the call statement.
Query q = entitymanager.createNativeQuery("{call sample_procedure(?,?)}").setParameter(1, inparam).setParameter(2, outparam);
q.executeUpdate();
It did not work. Did not return the output to java class.
Tried with this:
Query q = entitymanager.createNativeQuery("{call sample_procedure(?,?)}", Integer.class).setParameter(1, inparam).setParameter(2, outparam);
q.executeUpdate();
It did not work either. Did not return the output to java class.
Tried with this as well:
Query q = entitymanager.createNativeQuery("{call sample_procedure(?,?)}").setParameter(1, inparam).setParameter(2, outparam);
q.getSingleResult();
This also threw an exception: Cannot perform an update or delete operation on select query: "{call sample_procedure(?,?)}".
I believe it is not possible to do it like this as mentioned by Sean Patrick Floyd in the answer link i have provided above.(Note: I do not have the book :)) If you need to process your out parameter and if that is the reason you need it, you need to handle it logically. Seems its not possible in jpa2.0
I have some logic in procedure and inside loop I was incrementing the count.
First, in you given use case, count has to be declared INOUT (both input and output).
PROCEDURE sample_procedure(
id IN VARCHAR,
count INOUT NUMBER)
Then:
For JPA < 2.1 don't have support for getting back values from OUT or INOUT parameters. So, you are probably stuck if you need to stay with that version.
JPA >= 2.1 has explicit support for calling stored procedure using the EntityManager.html.createStoredProcedureQuery method:
count = getEm().createStoredProcedureQuery("sample_procedure")
.registerStoredProcedureParameter(1, String.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, Integer.class, ParameterMode.INOUT)
.setParameter(1, id)
.setParameter(2, count);
storedProcedure.execute();
int count = (Integer)storedProcedure.getOutputParameterValue(2);
Untested. Beware of typos !

Create method to return dataset

I'm trying to create a method to pass an ID number to a stored proc and return a dataset, this is what I have written so far, I am receiving an error message saying: "Not all code paths return a value", I'm not sure how I finish this. Would appreciate help!
public Int32 gvProjDetailsBind(Int32 ProjID)
{
String strConn = System.Configuration.ConfigurationManager.ConnectionStrings["Project_Tracker"].ConnectionString;
SqlConnection connDetails = new SqlConnection(strConn);
SqlCommand cmdDetails = new SqlCommand("USP_SelectProject", connDetails);
cmdDetails.CommandType = CommandType.StoredProcedure;
cmdDetails.Parameters.AddWithValue("#ProjectNumber", ProjID);
SqlDataAdapter daDetails = new SqlDataAdapter(cmdDetails);
DataSet dsDetails = new DataSet();
daDetails.Fill(dsDetails);
gvProjDetails.DataSource = dsDetails;
gvProjDetails.DataBind();
}
There are a few problems here...
1) Your method doesn't return anything.
You've declared a return type of Int32 but never return any value. The compiler won't allow this, because any code calling this method expects a value to be returned. So somewhere, likely at the end, you need a return statement which returns a value. (In this case an integer value.)
2) You claim you want to return a DataSet
The return type you've declared is Int32, not DataSet. If you want to return a DataSet then you need to change that return type in the method signature accordingly, and then (at the end of the method) return the DataSet. Something like this:
public DataSet gvProjDetailsBind(Int32 ProjID)
{
// the rest of the code
return dsDetails;
}
3) You're not separating your concerns
You claim that you want the method to return the DataSet, but at the end of the method you already use the DataSet:
gvProjDetails.DataSource = dsDetails;
gvProjDetails.DataBind();
What is code calling this method going to do with this DataSet? Normally the UI code would call a method like this to get the data and then bind it to elements (in this case gvProjDetails). You seem to be combining these concepts into a single block of code.
You are missing a return value. You can return 0 for example.
return 0;
should be enough. But what do you realy want to return?
In case of dsDetails, you should pass an out parameter and return dsDetails this way.

what are the OleDbTypes associated with Oracle Number and varchar2 when calling a function

I'm trying to map OleDb parameters to an Oracle Function. I was able to do this using the System.Data.Oracle namespace but then found that this is depricated, so I thought i would re-write it as OldDb to avoid installing the Oracle Provider.
I have defined the following oracle function as an example:
create function GetImagePath (AIRSNumber in number)
return varchar2
is
begin
return '\\aiimg524\images\Ofndrtrk\2010\01\0kvrv1p000lcs74j';
end;
and I'm calling it using the following code:
using (var command = new OleDbCommand())
{
command.Connection = con;
command.CommandText = ConfigurationManager.AppSettings[OTRAK_PHOTO_FUNC];
command.CommandType = CommandType.StoredProcedure;
string parm = ConfigurationManager.AppSettings[OTRAK_PHOTO_PARM];
command.Parameters.Add(parm, OleDbType.Decimal); // maps to oracle Number
command.Parameters[parm].Direction = ParameterDirection.Input;
command.Parameters[parm].Value = airsNumber;
command.Parameters.Add(RETURN_VALUE, OleDbType.Variant); // maps to Oracle varchar2
command.Parameters[RETURN_VALUE].Direction = ParameterDirection.ReturnValue;
try
{
con.Open();
command.ExecuteNonQuery();
path = command.Parameters[RETURN_VALUE].Value.ToString();
}
I tried a bunch of different OleDB types for the parameter and the return value. the current attempt is from a mapping table i found on the web that said number = decimal and varchar2 = variant. I'm about to try every permutation of types in the enum and wanted to ask for help. the not so useful error message i get is:
[System.Data.OleDb.OleDbException] = {"ORA-06550: line 1, column 7:\nPLS-00306: wrong number or types of arguments in call to 'GETIMAGEPATH'\nORA-06550: line 1, column 7:\nPL/SQL: Statement ignored"}
This actually had nothing to do with the type of the parameters but the order. Using the OleDb provider for Oracle does not respect the names of the parameters in the parameter collection but rather the order that the parameters are added. Wwhen calling an oracle function, the return value is a free parameter that must be declared first. by adding my return value parameter and then the actual function parameter things started working.
using the command.Parameters.AddWithValue(parm, value) also simplifies things a bit.

Resources