I have a procedure like this:
Procedure MyProc(param1 IN VARCHAR2 default 'default_value', param2 IN VARCHAR2 default null);
To debug this in PL-SQL i'm doing:
MyPackage.MyProc(param2 => '20130301');
And it's mapped in Nhibernate inside a hbm file:
<sql-query name="MyMappedProc">
<![CDATA[ call MyPackage.MyProc(param2 => :parametro2); ]]>
</sql-query>
and being called in application:
_Query = Session.GetNamedQuery("MyMappedProc");
_Query.SetParameter("parametro2", "value_var");
var lista = _Query.List<object>();
And I'm having this error:
{"ORA-00907: missing right parenthesis"}
Is there a way to call a procedure with optional parameters with NHibernate?
Thanks.
How I'm doing this in production code right now
<sql-query name="Recalc">
CALL P_DATA.RECALC.CONST_QUERY(:map, :id)
</sql-query>
and then from C# code
session.GetNamedQuery("Recalc").SetParameter("id", this.id)
.SetParameter("map", "MyMap").ExecuteUpdate();
As usual ShowSQL or the marvelous Ayende's NHibernate profiler are your friends
Related
I have written code to insert call parameterized stored procedure written in oracle pl/sql. I have given all parameters properly as displayed in below code.
function CallSp(str_id, ref_no, note, userId, strdatestamp, writtenDate)
Dim strcon2 : set strcon2=server.createObject("ADODB.Connection")
Dim strcmd2
Dim sql2
Dim ReturnVal
strcon2.Open "Proper Connectionstring provided here"
sql2 = "Fr_Store_Notes"
Set strcmd2 = Server.CreateObject("ADODB.Command")
Set strcmd2.ActiveConnection = strCOn2
strcmd2.CommandText = sql2
strcmd2.CommandType = 4
strcmd2.Parameters.Refresh
strcmd2.Parameters.Append strcmd2.CreateParameter("p_str_id", 12,1)
strcmd2.Parameters("p_str_id") = str_id
strcmd2.Parameters.Append strcmd2.CreateParameter("p_ref_no", 12,1)
strcmd2.Parameters("p_ref_no") = ref_no
strcmd2.Parameters.Append strcmd2.CreateParameter("p_UserId", 12,1)
strcmd2.Parameters("p_UserId") = userId
strcmd2.Parameters.Append strcmd2.CreateParameter("p_note", 12,1)
strcmd2.Parameters("p_note") = note
strcmd2.Parameters.Append strcmd2.CreateParameter("p_Datestamp", 12,1)
strcmd2.Parameters("p_Datestamp") = strdatestamp
strcmd2.Parameters.Append strcmd2.CreateParameter("p_WrittenDate", 12,1)
strcmd2.Parameters("p_WrittenDate") = writtenDate
strcmd2.Parameters.Append strCmd2.CreateParameter("p_return", 3, 2)
strcmd2.Execute
ReturnVal = strcmd2.Parameters("p_return").Value
CallSp=ReturnVal
set strCmd2=Nothing
strCon2.close
end function
But I am receiving error as
Parameter Type is not supported at the line strcmd2.Execute
Database stored procedure is as like below and working fine if we execute it from database
create or replace
procedure Fr_Store_Notes (
P_STR_ID IN VARCHAR2,
p_Ref_no in VARCHAR2,
P_UserId in VARCHAR2,
P_Note IN VARCHAR2,
P_datestamp IN VARCHAR2,
p_WrittenDate IN VARCHAR2,
p_return OUT number)
AS
BEGIN
--Expected Code Block is there and working fine
End;
Can anyone help me in sorting out this issue
Update: - Apparently after a bit of research (as I don't work with Oracle) ADODB doesn't support adVariant (which is 12) and you should use adVarChar (which is 200) instead.
See A: Classic ASP calling Oracle stored procedure with OraOleadb Driver
Leaving the rest of the answer below as it's probably still relevant once this issue is fixed.
The cause is of that particular error is usually a mismatch of data type once the ADODB talks to the provider defined by the connection.
Just looking at the procedure definition in Oracle in comparison to your ADODB.Command object I can see that the p_return parameter appears to be incorrect. I talk about this in a previous answer to a similar question.
According to Data Type Mapping (a great resource for Data Type Mapping in ADO) adInteger (which is 3) maps to Int in Oracle not Number. Instead, you should use adNumeric (which is 131) which should fix that particular error.
Try changing this line
strcmd2.Parameters.Append strCmd2.CreateParameter("p_return", 3, 2)
to
strcmd2.Parameters.Append strCmd2.CreateParameter("p_return", 131, 2)
Useful Links
A: Using Stored Procedure in Classical ASP .. execute and get results
A: ADODB.Parameters error '800a0e7c' Parameter object is improperly defined. Inconsistent or incomplete information was provided (recommend this to learn how to use METADATA in global.asa to have ADO Named Constants always available to an ASP Web Application)
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;
I'm using fluent nhibernate and I cannot use stored procedure and excute it.
I tried:
Session.GetNamedQuery("Select_All_Question_Groups");
and:
const string sql = "EXEC [dbo].[Stored_Procedure_Name] #PortalId=:PortalId";
return _session.CreateSQLQuery(sql).SetInt32("PortalId", portalId)
const string sql = "call [dbo].[Stored_Procedure_Name] #PortalId=:PortalId";
return _session.CreateSQLQuery(sql).SetInt32("PortalId", portalId)
const string sql = "EXEC [dbo].[Stored_Procedure_Name](PortalId=:PortalId)";
return _session.CreateSQLQuery(sql).SetInt32("PortalId", portalId)
But none of those options works.
when I use session.GetNamedQuery() I got error that the procedure does not exist.
In the other options there is no error, but the procedue does not change anything.
I have a Java app accessing an oracle stored procedure. The arguments to the stored procedure include an array type. I do it like the following...
con = this._getConnection();
Connection narrowdConn = (Connection)WSJdbcUtil.getNativeConnection( (WSJdbcConnection)con );
callable = con.prepareCall("{call MY_PKG.MY_PROCEDURE(?, ?)}");
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("VARCHAR2_ARR", narrowdConn);
ARRAY arrayArg1 = new ARRAY(arrayDescriptor, con, docNames);
ARRAY arrayArg2 = new ARRAY(arrayDescriptor, con, docTypes);
callable.setArray(1, arrayArg1);
callable.setArray(2, arrayArg2);
callable.execute();
Now, I am getting this Exception...
java.sql.SQLException: invalid name pattern: MY_PKG.VARCHAR2_ARR
VARCHAR2_ARR is a public TYPE, defined inside an Oracle Package like the following:
TYPE VARCHAR2_ARR IS TABLE OF VARCHAR2(50);
And used as such in my stored proc...
PROCEDURE MY_PROCEDURE
(V_ARR_ARG1 IN VARCHAR2_ARR,
V_ARR_ARG2 IN VARCHAR2_ARR)
the type VARCHAR2_ARR is a PLSQL type, you won't be able to interface it directly from java. I suggest you look into this thread on AskTom regarding a similar question.
Here are a couple suggestions:
create a SQL TYPE that you can bind from java
insert into a temporary table from java and read from it in plsql
In both cases you will have to either modify the PLSQL procedure or add a new translation procedure.
We need to set accessToUnderlyingConnectionAllowed falg true while creating a datasource
I did stuck at this problem. Hope this illustration might help you:
Steps to create the procedure in oracle.
Create type of the desired object as:
CREATE OR REPLACE TYPE STUDENT_TYPE IS OBJECT
( ID NUMBER,
NAME VARCHAR2(50));
Create another object of array as:
CREATE OR REPLACE TYPE STUDENT_ARRAY IS TABLE OF STUDENT_TYPE;
Create procedure to accepting array of object and do the desired operation, I am here just inserting the entries in table as:
CREATE OR REPLACE PROCEDURE SP_INSERT_STUDENT_RECORD_IN_BULK(
IN_STUDENT_RECORDS STUDENT_ARRAY) IS
BEGIN
FOR i IN IN_STUDENT_RECORDS.first.. IN_STUDENT_RECORDS.last
LOOP
BEGIN
INSERT INTO STUDENT(ID,NAME) VALUES
(IN_STUDENT_RECORDS(i).ID, IN_STUDENT_RECORDS(i).NAME)
END;
END LOOP:
END SP_INSERT_STUDENT_RECORD_IN_BULK;
Code snippet to call Procedure through Java
import org.springframework.jdbc.core.*;
import oracle.jdbc.OracleConnection;
....
List<Student> students = getStudentList();
try(Connection hikariCon = dataSource.getConnection()){
if(hikariCon.isWrapperFor(OracleConnection.class)){
OracleConnection con = hikariCon.unwrap(OracleConnection.class);
Object[] students = students.stream().map(student -> {
return con.createStruct(STUDENT_TYPE, new Object[]{
student.getId(),
student.getName()
});
}).collect(Collectors.list()).flatMap(List::stream).toArray();
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource)
.withProcedureName("SP_INSERT_STUDENT_RECORD_IN_BULK")
.declareParameters(
new SqlParameter("IN_STUDENT_RECORDS", Types.ARRAY));
jdbcCall.execute(con.createOracleArray(STUDENT_ARRAY,students))
}
} catch(Exception e){
log.error("Error due to- {}",e,getMessage());
}
How can I access the value of an out parameter of an oracle stored procedure in the .net code - Oracle stored procedure being called via Nhibernate?
Sample working code would help.
You have to use the latest version of NHibernate (2.1.2).
<sql-query name="ReturnSomethig" callable="true">
<return class="Somethig" />
{ call ReturnSomethig(:someParameter) }
</sql-query>
The Oracle Stored Procedure need to has the first parameter as a out sys_refcursor parameter.
And you can call the named query like that:
IQuery query = currentSession.GetNamedQuery("ReturnSomethig");
query.SetInt64("someParameter", someParameter);
var somethig = query.List<Somethig>();
And it will work.
I tried the 2.1.2 libraries without much luck. I had to actually make some modifications to the library based on this article. If you go this route, you'll want to make sure you are using the Oracle.DataAccess dll since it won't work with System.DataAccess.OracleClient dll.
Whilst looking into getting out parameters from NHibernate I found various links suggesting that to get a stored proc out parameter value (rather than using a refcursor) you need to construct the command in code rather than using the XML mappings file.
But I found difficulty finding a complete working example online. It's not a beautiful solution, but I post in case it helps someone.
Example Oracle stored proc:
create or replace PACKAGE BODY MY_PACKAGE AS
PROCEDURE add_one
(
p_out out number,
p_in in number
) AS
BEGIN
select p_in + 1 into p_out from dual;
END add_one;
END MY_PACKAGE;
Example C# code, where sessionFactory is an NHibernate ISessionFactory:
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var command = session.Connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "MY_PACKAGE.add_one";
var parmOut = command.CreateParameter();
parmOut.ParameterName = "p_out";
parmOut.DbType = DbType.Decimal;
parmOut.Direction = ParameterDirection.Output;
command.Parameters.Add(parmOut);
var parmIn = command.CreateParameter();
parmIn.ParameterName = "p_in";
parmIn.DbType = DbType.Decimal;
parmIn.Direction = ParameterDirection.Input;
parmIn.Value = 67;
command.Parameters.Add(parmIn);
transaction.Enlist(command);
command.ExecuteNonQuery();
int sixtyEight = (int) (decimal) parmOut.Value;
}
See this comment by Richard Brown. Some sample code can be found here.
Unfortunately I can't test it so I don't know whether it works or not.
A belated reply.
For oracle, out parameter is not supported by nHibernate unless it is a cursor. If you just want a scalar value, a work around is to wrap your stored procedure with an oracle function.
Then you can do this
<sql-query name="TestOracleFunction" callable="true">
<return-scalar column="MyOutputValue" type="String" />
<![CDATA[
select MyOracleFunction as MyOutputValue from dual
]]>
</sql-query>
This works!