I have this sys_refcursor function in a package
function frcBaanCompanies return SYS_REFCURSOR is
x sys_refcursor;
begin
open x for select t$comp, t$cpnm from baan.tttaad100000 order by t$comp;
return x;
end;
and a net method calling this as so
listBox1.DataSource = lO.fRefCursor("priceWorx.frcBaanCompanies", null, false).Tables[0];
Here's how I call the function:
public DataSet fRefCursor(String refCursorName, IDictionary<string, string> prms, bool leaveConnectionOpen = true)
{
try
{
using (OracleCommand cmd = new OracleCommand("", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = refCursorName;
if (prms!=null) SetupParams(refCursorName, cmd, prms);
using (OracleDataAdapter da = new OracleDataAdapter(cmd))
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
cmd.Connection = conn;
}
using (DataSet ds = new DataSet())
{
da.Fill(ds);
return ds;
}
}
}
}
catch (Exception ex)
{
Debugger.Break();
Debug.WriteLine(ex);
return null;
}
finally
{
if (!leaveConnectionOpen) conn.Close();
}
}
The same method works fine when called with parameters(some other cursor function, but fails with
ORA-06550: line 1, column 7:
PLS-00221: 'FRCBAANCOMPANIES' is not a procedure or is undefined
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
works fine when executed within (Oracle) sql developer too..
What am I doing wrong ?
This is because you can't call a function without parameters, but you could call it with null parameters. What you are currently calling when you do not input any parameters is:
FRCBAANCOMPANIES;
and this is different to
variable := FRCBAANCOMPANIES;
In the first case oracle is looking for a procedure without any return and in the second case you call your function. So you have to set the return parameter also if you do not need it.
Related
I'm sort of having a hard time with this one. Well ok, I have two different solutions (solution1 has a WebApplication Project; solution2 has a Website Project). Inside the two solutions, there's a WCF service structure. I have the exact same code in both services (in their respective solutions). My code compiles just fine. From the service I do a simple call to a procedure that returns a cursor. When I execute the service from the WebApplication it works just fine; when I do the same from the Website I get error: "wrong number or types of arguments". They both call the same procedure, in the same DB. And I triple check my code, and is the same in both services. Any ideas or suggestions? My code is as follows in both solutions:
Service.cs
public List<A1001310> SearchClient_A1001310()
{
DataTable dataTable = new DataTable();
dataTable = DataManager.SearchClient();
List<A1001310> list = new List<A1001310>();
list = (from DataRow dr in dataTable.Rows
select new A1001310()
{
Id = Convert.ToInt32(dr["CLIENT_ID"]),
//ClientName = dr["NOM_CLIENTE"].ToString()
}).ToList();
return list;
}
DataManager.cs
public static DataTable SearchClient()
{
try
{
using (OleDbCommand cmd = new OleDbCommand(packetName + ".select_A1001310"))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlManager sqlManager = new SqlManager();
return sqlManager.GetDataTable(cmd);
}
}
catch (Exception ex)
{
//TODO; Handle exception
}
return null;
}
The call to DataTable is:
public DataTable GetDataTable(OleDbCommand cmd)
{
using (DataSet ds = GetDataSet(cmd))
{
return ((ds != null && ds.Tables.Count > 0) ? ds.Tables[0] : null);
}
}
public DataSet GetDataSet(OleDbCommand cmd)
{
using (DataSet ds = new DataSet())
{
this.ConvertToNullBlankParameters(cmd);
using (OleDbConnection conn = new OleDbConnection(cmd.Connection == null ? _dbConnection : cmd.Connection.ConnectionString))
{
cmd.Connection = conn;
cmd.CommandTimeout = _connTimeout;
conn.Open();
//cmd.ExecuteScalar();
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
da.Fill(ds);
}
return ds;
}
}
The procedure is as follow:
PROCEDURE select_A1001310(io_cursor OUT lcursor_data)
AS
BEGIN
OPEN io_cursor FOR
--
SELECT client_id
FROM a1001310
WHERE status = 'A'
--
EXCEPTION
WHEN OTHERS THEN
IF io_cursor%ISOPEN THEN
CLOSE io_cursor;
END IF;
--REVIRE: EXCEPTION HANDLER
END select_A1001310;
So if it helps anyone, I resolved my issue by specifying the OUT parameter declared in the procedure. This resulted in me changing from Oledb to OracleClient as follow:
public static DataTable SearchClient()
{
string connection = ConfigurationManager.ConnectionStrings["DBConnection_Oracle"].ToString();
string procedure = packetName + ".p_search_client";
OracleParameter[] parameters = new OracleParameter[1];
parameters[0] = new OracleParameter("io_cursor", OracleType.Cursor, 4000, ParameterDirection.Output, true, 0, 0, "", DataRowVersion.Current, String.Empty);
DataTable dt = new DataTable();
dt = DataManager_Oracle.GetDataTable_(connection, procedure, parameters);
return dt;
}
It seems that on the Website environment it didn't like leaving out the OUT parameter; whereas on the WebApplication I did not specify it, and it worked just fine... If some one know the why , PLEASE let me know :)
I want to test an Oracle Stored Procedure by using jmeter.I have done everything but parameters.
And here is my SQL Query:
declare
outinfo varchar2(20);
outtable sys_refcursor;
begin
{call RK_JSCX(?,?)};
end;
The outtable in Oracle is a cursor.And i used resultSet to contain it in java.However,whatever i set in parameter types ,it said invalid type.
Sample Start: 2012-10-25 16:06:41 CST
Load time: 0
Latency: 0
Size in bytes: 25
Headers size in bytes: 0
Body size in bytes: 25
Sample Count: 1
Error Count: 1
Response code: null 0
Response message: java.sql.SQLException: Invalid data type: cursor
Response headers:
oracle.jdbc.driver.T4CConnection#58ba09
SampleResult fields:
ContentType: text/plain
DataEncoding: UTF-8
How can fix it?
Thanks!
Here is my code in java:
public String RK_JSCX() throws Exception {
RK_JSCX_Response response = null;
List<RK_JSCX_Outtable> list = null;
Connection con = null;
CallableStatement cs = null;
ResultSet rs = null;
String sql = null;
try {
sql = "{call RK_JSCX(?,?)}";
con = ConnectionUtils.getInstance().getConnect();
if (con.isClosed()) {
throw new IllegalStateException("ERROR.THE CONNECTION ISCLOSED");
}
cs = con.prepareCall(sql);
cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cs.registerOutParameter(2, Types.VARCHAR);
cs.execute();
rs = (ResultSet) cs.getObject(1);
list = new ArrayList<RK_JSCX_Outtable>();
while (rs.next()) {
RK_JSCX_Outtable out = new RK_JSCX_Outtable(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getInt(5), rs.getString(6));
list.add(out);
}
String outInfo = cs.getString(2);
response = new RK_JSCX_Response(list, outInfo);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (rs != null) {
rs.close();
if (cs != null) {
cs.close();
}
if (con != null) {
con.close();
}
}
} catch (SQLException e) {
System.out.println("Exception2");
e.printStackTrace();
}
}
return JSON.toJSONString(response);
}
This is how to do it:
SQL Query : call RK_JSCX(?,?)
Parameter values : OUT, OUT
Parameter types : OUT -10,OUT VARCHAR
-10 being the int value of OracleTypes.CURSOR
Variable names: cursor, outInfo
Names are what you want
JMeter allows using more types than java.sql.Types constants, in this case instead of using Constant names, you use integer values of constants.
Documentation has been clarified (in next JMeter version) , see:
https://issues.apache.org/bugzilla/show_bug.cgi?id=54048
Try with the following changes
change the syntax in calling the procedure to
cs = con.prepareCall("BEGIN RK_JSCX(?, ?); END;");
And I believe your first OUT parameter is VARCHAR2 right? so
cs.registerOutParameter(1, Types.VARCHAR);
then
use the following to cast CallableStatement
rs = ((OracleCallableStatement)cs).getCursor(2);
Update 1
I have changed your procedure to demonstrate working version
Procedure
CREATE OR REPLACE PROCEDURE rk_jscx (outtable OUT sys_refcursor,
outinfo OUT VARCHAR2
)
AS
BEGIN
OPEN outtable FOR
SELECT SYSDATE
FROM DUAL;
outinfo := 1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
outinfo := 2;
ROLLBACK;
END rk_jscx;
Java Code
CallableStatement stmt = conn.prepareCall("BEGIN rk_jscx(?, ?); END;");
stmt.registerOutParameter(1, OracleTypes.CURSOR);
stmt.registerOutParameter(2, Types.VARCHAR);
stmt.execute();
ResultSet rs = ((OracleCallableStatement)stmt).getCursor(1);
while (rs.next()) {
System.out.println(rs.getDate("sysdate"));
}
The above prints 2012-10-23
Check your jdbc driver as well
I am wrote stored procedure to Insert data into database table but i am not getting how to pass datatable to stored procedure kindly tell how to use it.
below is my storedprocedure
CREATE OR REPLACE PROCEDURE PR_SREE_TEST(p_recordset In SYS_REFCURSOR) IS
Contrac_rc SREE_TEST%rowtype;
BEGIN
Loop
Fetch p_recordset Into Contrac_rc;
EXIT WHEN p_recordset%NOTFOUND;
Insert into SREE_TEST(CT,DESC,FLAG)
Values(Contrac_rc.CT,Contrac_rc.DESC,Contrac_rc.FLAG);
End Loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END PR_SREE_TEST;
/
and cs page
public DataSet sreetest(DataTable dt)
{
DataSet dsRegularIndentdtl = new DataSet();
try
{
OracleConnection OraConn = new OracleConnection(strDBConnection);
OraConn.Open();
OracleCommand OraCmd = new OracleCommand();
OraCmd.Connection = OraConn;
OraCmd.CommandText = "PR_SREE_TEST";
OraCmd.CommandType = CommandType.StoredProcedure;
OracleParameter parameter = new OracleParameter();
var recordSet1 = new DataTable();
recordSet1 = dt;
OraCmd.Parameters.Add("p_recordset", OracleDbType.RefCursor, recordSet1, ParameterDirection.Input);
OraCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
return dsRegularIndentdtl;
}
}
above is my code it is saying that p_recordset not valied. please tell me how to execute it.
Make sure you are using the correct overload of OraCmd.Parameters.Add(),
As per msdn the fourth parameter is not parameter direction, it is as below
public OracleParameter Add(
string parameterName,
OracleType dataType,
int size,
string srcColumn
)
In H2, I have written a Java decode function. It works with the code:
String sql = "select decode(1.0,2.0,3.0,4.0) from dual ;";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet resultSet = (ResultSet) stmt.executeQuery();
But the code
String sql = "select 6.0 - decode(1.0,2.0,3.0,4.0) from dual ;";
gives the error:
org.h2.jdbc.JdbcSQLException: Hexadecimal string with odd number of characters: "6.0"; SQL statement:
select 6.0 - decode(1.0,2.0,3.0,4.0) from dual ; [90003-157]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
at org.h2.message.DbException.get(DbException.java:167)
at org.h2.message.DbException.get(DbException.java:144)
at org.h2.util.StringUtils.convertHexToBytes(StringUtils.java:943)
at org.h2.value.Value.convertTo(Value.java:826)
at org.h2.expression.Operation.getValue(Operation.java:108)
at org.h2.command.dml.Select.queryFlat(Select.java:518)
at org.h2.command.dml.Select.queryWithoutCache(Select.java:617)
at org.h2.command.dml.Query.query(Query.java:298)
at org.h2.command.dml.Query.query(Query.java:268)
at org.h2.command.dml.Query.query(Query.java:37)
at org.h2.command.CommandContainer.query(CommandContainer.java:80)
at org.h2.command.Command.executeQuery(Command.java:181)
at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:96)
My decode function is as:
public final static Value decode(Value expression, Value ... paramValues) {
boolean param = true;
boolean hit = false;
Value returnValue = null;
Value defaultValue = null;
// Walk through all parameters, alternately the 'param' and corresponding 'value'.
// If 'param' is equal the expression, then return the next 'value'.
// If no hit, the return the last 'param' value as default value.
for (Value str : paramValues) {
if (param) {
defaultValue = str; // In case this is the last parameter.
// Remember the hit. The next value will be returned.
hit = (MiscUtil.equals(expression, str));
} else {
if (hit) {
returnValue = str;
break; // return str;
}
defaultValue = null;
}
param = ! param;
}
return (returnValue==null) ? defaultValue : returnValue;
}
Is there anything wrong with my decode function?
I have tried to return Object instead of Value in the decode function, and added this code at the end:
Object returnObject=null;
if (returnValue instanceof ValueDecimal) {
returnObject = ((ValueDecimal)returnValue).getBigDecimal();
} else if (returnValue instanceof ValueString) {
returnObject = ((ValueString)returnValue).getString();
} else if (returnValue instanceof ValueDate) {
returnObject = ((ValueDate)returnValue).getDate();
}
return returnValue;
But the I got:
org.h2.jdbc.JdbcSQLException: Data conversion error converting "aced0005737200146a6176612e6d6174682e426967446563696d616c54c71557f981284f0300024900057363616c654c0006696e7456616c7400164c6a6176612f6d6174682f426967496e74656765723b787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200146a6176612e6d6174682e426967496e74656765728cfc9f1fa93bfb1d030006490008626974436f756e744900096269744c656e67746849001366697273744e6f6e7a65726f427974654e756d49000c6c6f776573745365744269744900067369676e756d5b00096d61676e69747564657400025b427871007e0002fffffffffffffffffffffffefffffffe00000001757200025b42acf317f8060854e0020000787000000001287878"; SQL statement:
select 6.0 - cast(decode(1.0,2.0,3.0,4.0) as double) xxx from dual ; [22018-157]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
at org.h2.message.DbException.get(DbException.java:156)
at org.h2.value.Value.convertTo(Value.java:855)
at org.h2.expression.Function.getSimpleValue(Function.java:733)
at org.h2.expression.Function.getValueWithArgs(Function.java:893)
at org.h2.expression.Function.getValue(Function.java:432)
at org.h2.expression.Operation.getValue(Operation.java:113)
at org.h2.expression.Alias.getValue(Alias.java:35)
...
I also did some try with ValueExpression without luck.
Full support for decode in H2 would be the best solution. Is that something you can provide Thomas?
H2 thinks the data type is JAVA_OBJECT, and therefore wants to convert the parameters (6.0 and the result of the decode) to JAVA_OBJECT, which means first convert to a byte array. This fails.
I didn't test it myself, but explicit CAST should work:
select 6.0 - cast(decode(1.0,2.0,3.0,4.0) as double) from dual
It's a bit ugly I know.
We're really lost on this one, having read the ODP.NET 2 Day+ developer guide hasn't helped. I've provided the function definition (stored in a package), I don't understand what we have to cast the dataset to or what to pass the function. Here is the function definition:
FUNCTION ins (
rec_data IN OUT schema.table%ROWTYPE,
p_rowid OUT ROWID,
p_execution_ts IN schema.table.update_ts%TYPE)
RETURN NUMBER
Here is what we have done (which does nothing):
// inserts data
public void insertData(DataSet Data)
{
string connStr = "DATA SOURCE=someValidConnString";
OracleConnection conn = new OracleConnection(connStr);
string rowID = String.Empty;
Int32 rtnVal = 0;
try
{
conn.Open();
OracleCommand insCmd = new OracleCommand("PACKAGE.ins", conn);
insCmd.CommandType = CommandType.StoredProcedure;
OracleParameter outParam2 = new OracleParameter("retVal", OracleDbType.Varchar2, rtnVal,
ParameterDirection.ReturnValue);
insCmd.Parameters.Add(outParam2); //return value
OracleParameter inParam1 = new OracleParameter("rec_data", OracleDbType.NVarchar2, dsACCTData.Tables
[0].Rows[0], ParameterDirection.InputOutput);
OracleParameter outParam = new OracleParameter("p_rowid", OracleDbType.Varchar2, rowID,
ParameterDirection.Output);
OracleParameter inParam2 = new OracleParameter("p_execution_ts", OracleDbType.Date,
Oracle.DataAccess.Types.OracleDate.GetSysDate(), ParameterDirection.Input);
insCmd.Parameters.Add(inParam1); //first in out parameter
insCmd.Parameters.Add(outParam); //second out parameter
insCmd.Parameters.Add(inParam2); //third in parameter
insCmd.ExecuteNonQuery();
conn.Close();
}
catch (OracleException ee)
{
throw ee;
}
finally
{
conn.Dispose();
}
}
I know this is a vry specific question but I'm really lost. Let's assume the Oracle function ins works (it does), in this instance we simply don't know how to call it correctly using ODP.NET
Many thanks for any help.
edit: here is the error message:
ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'INS'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Kind regards,
Fugu
maybe this could help:
http://www.c-sharpcorner.com/UploadFile/john_charles/CallingOraclestoredproceduresfromMicrosoftdotNET06222007142805PM/CallingOraclestoredproceduresfromMicrosoftdotNET.aspx
I'm looking for the same answer and I think I found something. There is example of the output variable in second row.
objCmd.Parameters.Add("pin_deptno", OracleType.Number).Value = 20;
objCmd.Parameters.Add("pout_count", OracleType.Number).Direction = ParameterDirection.Output;
Hope that link will do any good.
Regards, M
Every thing looks good. But you have to check all attribute name and attribute types.
In your example have bad data type OracleDbType.Varchar2, because your function return Number (in your Oracle Function definition)
OracleParameter outParam2 = new OracleParameter("retVal", OracleDbType.Varchar2, rtnVal,
ParameterDirection.ReturnValue);
insCmd.Parameters.Add(outParam2); //return value