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

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.

Related

Postgres datatype conversion differ on Ubuntu and windows

I am getting following exception on windows while running the below
ERROR: operator does not exist: numeric = character varying Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts." while executing with query parameter
I am passing the Numeric String for parameter using function as a named parameter to the query
getUIDCount(String id) {
...
select count(UID) as icrd FROM UID_tbl WHERE id = ?
...
}
where id is numeric(5,0)" in table
Everything works well on Ubuntu but getting Error while running the same code on windows. I have to do the explicit casting just for windows. I am using PostgreSQL 9.4.3. I am using "org.hibernate.dialect.PostgreSQLDialec" and grails 2.3.11 with runtime 'org.postgresql:postgresql:9.3-1100-jdbc41'
updated with how it is getting called
def Integer getUIDSetSize(String _id)
{
Integer i = 0;
Sql sql = new Sql(dataSource);
String sqlt = """select count(UID) as icrd FROM UID_tbl WHERE _id = ?""";
log.trace(sqlt);
sql.eachRow(sqlt, [_id], { row -> i = row.icrd; });
return i;
}
This how it get called def _id1 = params._id1; count1 = HelperService.getUIDSetSize(_id1)
The workaround for casting from varchar to numeric is
CREATE CAST(VARCHAR AS NUMERIC) WITH INOUT AS IMPLICIT;
This is not the best solution and would suggest selective casting from the code.

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 retrieve multiple row from oracle 10g table through jsp page

I want to retrieve multiple row from oracle 10g tables through JSP using prepare statement.
The following JSP code creates a prepared statement:
String myquery = "SELECT * FROM EMPLOYEES WHERE DEPARTMENT = ?";
PreparedStatement mystatement = connection.prepareStatement(myquery);
The first line stores the SQL statement in a string variable called myquery , with a question mark ( ? ) serving as a placeholder for the SQL variable value. The second line creates a prepared statement object called mystatement .
Next, you assign a value to the SQL variable, as follows:
mystatement.setString(1, request.getParameter("myURLparam"));
The setString method assigns the value to the variable and takes two arguments. The first argument specifies the affected variable by its position (here, the first position in the SQL statement). The second argument specifies the variable's value. In this example, the value is provided by a URL parameter passed to the page.
Note: You must use different methods to assign non-string values to SQL variables. For example, to assign an integer to the variable, you would use the mystatement.setInt() method.
Finally, you generate the recordset, as follows:
ResultSet myresults = mystatement.execute();
Please find the sample code below from the below link http://oracle.ittoolbox.com/groups/technical-functional/oracle-apps-l/how-to-connect-to-database-in-jsp-using-jdbc-drivers-to-oracle-database-1569382
<%# page import="java.io.*, java.util.*, java.sql.*"%>
<%# page import="oracle.jdbc.driver.OracleConnection" %>
<%
OracleConnection conn1 = null;
ResultSet getCountRs = null;
PreparedStatement getCountStmt = null;
try{
conn1 = (OracleConnection)TransactionScope.getConnection();
getCountStmt = conn1.prepareStatement("SELECT
PROMPT,FUNCTION_ID,SUB_MENU_ID FROM FND_MENU_ENTRIES_VL WHERE MENU_ID
=:1 and prompt is not null");
getCountStmt.setInt(1,pMenuid);
getCountRs = getCountStmt.executeQuery();
while(getCountRs.next())
{
prompt[x]=getCountRs.getString(1);
function_id[x]=getCountRs.getInt(2);
submenu_id[x]=getCountRs.getInt(3);
x++;
}
}
catch(exception e) {}
%>

How to call an Oracle function with a Ref Cursor as Out-parameter from C#?

I'm using a product that provides a database API based on Oracle functions and I'm able to call functions via ODP.NET in general. However, I can't figure out, how to call a function that includes a Ref Cursor as Out-parameter. All the samples I found so far either call a procedure with Out-parameter or a function with the Ref Cursor as return value. I tried to define the parameters similiarly, but keep getting the error that the wrong number or type of parameters is supplied.
Here is the function header (obviously obfuscated):
FUNCTION GetXYZ(
uniqueId IN somepackage.Number_Type,
resultItems OUT somepackage.Ref_Type)
RETURN somepackage.Error_Type;
These are the type definitions in "somepackage":
SUBTYPE Number_Type IS NUMBER(13);
TYPE Ref_Type IS REF CURSOR;
SUBTYPE Error_Type IS NUMBER;
And this is the code that I have tried:
string sql = "otherpackage.GetXYZ";
var getXYZCmd = OracleCommand oracleConnection.CreateCommand(sql);
getXYZCmd.CommandType = CommandType.StoredProcedure;
getXYZCmd.Parameters.Add("uniqueId", OracleDbType.Int32).Value = uniqueExplosionId;
getXYZCmd.Parameters.Add("resultItems", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
getXYZCmd.Parameters.Add("return_value", OracleDbType.Int32).Direction = ParameterDirection.ReturnValue;
The I tried the following different ways to call the function (of course only one at a time):
var result = getXYZCmd.ExecuteNonQuery();
var reader = getXYZCmd.ExecuteReader();
var scalarResult = getXYZCmd.ExecuteScalar();
But each of them fails with the error message:
Oracle.DataAccess.Client.OracleException: ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored.
So is it generally possible to call a function with a Ref Cursor as Out-parameter from C# with ODP.NET? I can call a function with the same structure with a Varchar2-Out-parameter instead of the Ref Cursor without problems...
Btw, I'm using ODP.NET version 2.112.2.0 from C#.NET 3.5 in Visual Studio 2008.
Thanks in advance for your help!
You sure can. There are a few gotchas to be wary of but here is a test case
create or replace function testodpRefCursor(
uniqueId IN NUMBER
,resultItems OUT NOCOPY SYS_REFCURSOR) RETURN NUMBER
IS
BEGIN
OPEN resultItems for select level from dual connect by level < uniqueId ;
return 1;
END testodpRefCursor;
I have found that
functions likes to have the
ReturnValue as THE FIRST param
in the collection
BindByName is by default FALSE, so it defaults to BIND BY POSITION
Otherwise it is quite straight forward:
OracleCommand cmd = new OracleCommand("TESTODPREFCURSOR", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
// Bind
OracleParameter oparam = cmd.Parameters.Add("ReturnValue", OracleDbType.Int64);
oparam.Direction = ParameterDirection.ReturnValue ;
OracleParameter oparam0 = cmd.Parameters.Add("uniqueId", OracleDbType.Int64);
oparam0.Value = 5 ;
oparam0.Direction = ParameterDirection.Input;
OracleParameter oparam1 = cmd.Parameters.Add("resultItems", OracleDbType.RefCursor);
oparam1.Direction = ParameterDirection.Output;
// Execute command
OracleDataReader reader;
try
{
reader = cmd.ExecuteReader();
while(reader.Read() ){
Console.WriteLine("level: {0}", reader.GetDecimal(0));
}
} ...
Now for more samples go to your Oracle Home directory and look # the Ref cursor samples in ODP.NET
for instance:
%oracle client home%\odp.net\samples\4\RefCursor
hth

How to return a RefCursor from Oracle function?

I am trying to execute a user-defined Oracle function that returns a RefCursor using ODP.NET. Here is the function:
CREATE OR REPLACE FUNCTION PKG.FUNC_TEST (ID IN TABLE.ID%type)
RETURN SYS_REFCURSOR
AS
REF_TEST SYS_REFCURSOR;
BEGIN
OPEN REF_TEST FOR
SELECT *
FROM TABLE;
RETURN REF_TEST;
END;
/
I can call this function in Toad (select func_test(7) from dual) and get back a CURSOR. But I need to get the cursor using C# and ODP.NET to fill a DataSet, but I keep getting a NullReferenceException - "Object reference not set to an instance of an object". Here is what I have for that:
OracleConnection oracleCon = new OracleConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
OracleCommand sqlCom = new OracleCommand("select func_test(7) from dual", oracleCon);
sqlCom.Parameters.Add("REF_TEST", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
OracleDataAdapter dataAdapter = new OracleDataAdapter();
dataAdapter.SelectCommand = sqlCom;
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet); //FAILS HERE with NullReferenceException
I was able to find lots of info and samples on using stored procedures and ODP.NET, but not so much for returning RefCursors from functions.
EDIT: I do not want to explicitly add input parameters to the OracleCommand object (i.e. sqlCom.Parameters.Add("id", OracleDbType.Int32,ParameterDirection.Input).Value = 7;) as that makes it difficult to implement this as a generic RESTful web service, but I'm reserving it as my last resort but would use stored procedures instead.
Any help is much appreciated!
I think you are missing the sqlCom.ExecuteNonQuery();
also, instead of running the select func_test(7) from dual; lets switch it to run the function and pass in the param
OracleConnection oracleCon = new OracleConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
// Set the command
string anonymous_block = "begin " +
" :refcursor1 := func_test(7) ;" +
"end;";
//fill in your function and variables via the above example
OracleCommand sqlCom= con.CreateCommand();
sqlCom.CommandText = anonymous_block;
// Bind
sqlCom.Parameters.Add("refcursor1", OracleDbType.RefCursor);
sqlCom.Parameters[0].Direction = ParameterDirection.ReturnValue;
try
{
// Execute command; Have the parameters populated
sqlCom.ExecuteNonQuery();
// Create the OracleDataAdapter
OracleDataAdapter da = new OracleDataAdapter(sqlCom);
// Populate a DataSet with refcursor1.
DataSet ds = new DataSet();
da.Fill(ds, "refcursor1", (OracleRefCursor)(sqlCom.Parameters["refcursor1"].Value));
// Print out the field count the REF Cursor
Console.WriteLine("Field count: " + ds.Tables["refcursor1"].Columns.Count);
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
finally
{
// Dispose OracleCommand object
cmd.Dispose();
// Close and Dispose OracleConnection object
con.Close();
con.Dispose();}
this is based on the example ODP that can be found # %ora_home%\Client_1\ODP.NET\samples\RefCursor\Sample5.csproj
If you want to avoid (for better or worst!) the custom built param collection for each proc/function call you can get around that by utilizing anonymous blocks in your code, I have ammended (once again untested!) the code above to reflect this technique.
Here is a nice blog (from none other than Mark Williams) showing this technique.
http://oradim.blogspot.com/2007/04/odpnet-tip-anonymous-plsql-and.html

Resources