Enable query logging in SQL Server - c++11

ALL,
I'm trying to execute following code:
SQLHSTMT stmt = 0;
SQLHDBC hdbc;
SQLLEN cbName, cbTableName = SQL_NTS, cbSchemaName = SQL_NTS;
long id;
int result = 0;
std::wstring query;
SQLWCHAR *qry = NULL, *tname = NULL, *sname = NULL;;
if( pimpl->m_subtype == L"Microsoft SQL Server" || pimpl->m_subtype == L"Sybase" || pimpl->m_subtype == L"ASE" )
query = L"SELECT object_id FROM sys.objects o, sys.schemas s WHERE s.schema_id = o.schema_id AND o.name = ? AND s.name = ?;";
qry = new SQLWCHAR[query.length() + 2];
tname = new SQLWCHAR[tableName.length() + 2];
sname = new SQLWCHAR[schemaName.length() + 2];
memset( tname, '\0', tableName.length() + 2 );
memset( sname, '\0', schemaName.length() + 2);
uc_to_str_cpy( sname, schemaName );
uc_to_str_cpy( tname, tableName );
memset( qry, '\0', query.length() + 2 );
uc_to_str_cpy( qry, query );
SQLRETURN retcode = SQLAllocHandle( SQL_HANDLE_DBC, m_env, &hdbc );
SQLSMALLINT OutConnStrLen;
retcode = SQLDriverConnect( hdbc, NULL, m_connectString, SQL_NTS, NULL, 0, &OutConnStrLen, SQL_DRIVER_NOPROMPT );
auto dbName = new SQLWCHAR[pimpl->m_dbName.length() + 2];
memset( dbName, '\0', pimpl->m_dbName.length() + 2 );
uc_to_str_cpy( dbName, pimpl->m_dbName );
retcode = SQLSetConnectAttr( hdbc, SQL_ATTR_CURRENT_CATALOG, dbName, SQL_NTS );
delete[] dbName;
dbName = nullptr;
retcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &stmt );
retcode = SQLPrepare( stmt, qry, SQL_NTS );
SQLSMALLINT dataType[2], decimalDigit[2], nullable[2];
SQLULEN parameterSize[2];
retcode = SQLDescribeParam( stmt, 1, &dataType[0], &parameterSize[0], &decimalDigit[0], &nullable[0] );
retcode = SQLBindParameter( stmt, 1, SQL_PARAM_INPUT, SQL_C_DEFAULT, dataType[0], parameterSize[0], decimalDigit[0], tname, 0, &cbTableName );
retcode = SQLDescribeParam( stmt, 2, &dataType[1], &parameterSize[1], &decimalDigit[1], &nullable[1] );
retcode = SQLBindParameter( stmt, 2, SQL_PARAM_INPUT, SQL_C_DEFAULT, dataType[1], parameterSize[1], decimalDigit[1], sname, 0, &cbSchemaName );
retcode = SQLExecute( stmt );
retcode = SQLBindCol( stmt, 1, SQL_C_SLONG, &id, 100, &cbName );
retcode = SQLFetch( stmt );
if( retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO && retcode != SQL_NO_DATA )
{
GetErrorMessage( errorMsg, 1, stmt );
result = 1;
}
else if( retcode == SQL_NO_DATA )
tableId = 0;
delete[] qry;
qry = NULL;
delete[] tname;
tname = NULL;
delete[] sname;
sname = NULL;
(error checking is omitted for clarity)
When executing, everything is succeeded, except SQLFetch() which doesn't return any rows and therefore tableId will be 0.
The weird thing is - running the query in the SQL Server Studio succeeds and the row is returned.
Can someone please explain how is it possible?
Or better yet - explain to me how can I get the exact query executed on the server to be logged.
Because trying to do Server -> Management -> SQL Logs and choosing a "Current Log" I can only see queries that are crashing..
TIA!!
And yes - I'm using 2008 SQL Server for testing purposes.

Related

Output parameter is empty when calling Oracle package procedure using Oracle ADO in VBScript

I need to call Oracle package procedure from VBScript (from PowerDesigner app). It is 64-bit application so i am using Oracle 64-bit ODBC driver (Oracle client 12.1.0.2).
The job should be done with following code, which runs without any error but output values are empty:
Const ORAUser = "****"
Const ORAPass = "****"
Const ORASchema = "****"
Const ORAInst = "****"
Const ORADRV = "Oracle in OraClient12Home1"
Const ADO_CMD_STORED_PROC = 4
Dim Conn, ConnString, CmdStoredProc
Set Conn = CreateObject("ADODB.Connection")
ConnString = "Driver={" + ORADRV + "};Dbq=" + ORAInst + ";Uid=" + ORAUser + ";Pwd=" + ORAPass + ";"
Conn.Open ConnString
Set CmdStoredProc = CreateObject("ADODB.Command")
With CmdStoredProc
Set .ActiveConnection = Conn
.CommandText = ORASchema & ".PDLOCKS_ADMIN.VBS_TEST"
.CommandType = ADO_CMD_STORED_PROC
.Parameters.Append CmdStoredProc.CreateParameter("i_input_num", 5, 1, 0, 1)
.Parameters.Append CmdStoredProc.CreateParameter("i_input_vchar", 200, 1, 4000, "1")
.Parameters.Append CmdStoredProc.CreateParameter("o_output_num", 5, 2, 0)
.Parameters.Append CmdStoredProc.CreateParameter("o_output_vchar", 200, 2, 4000)
.Execute
Output .Parameters("o_output_num").Value ' EMPTY :-(
Output .Parameters(2) ' EMPTY :-(
End With
Conn.Close
Set Conn = Nothing
Set CmdStoredProc = Nothing
In Oracle database package procedure is everything processed correctly and input and output parameters are saved into table TEST:
PROCEDURE VBS_TEST (
i_input_num in number
,i_input_vchar in varchar2
,o_output_num out number
,o_output_vchar out varchar2
)
IS
BEGIN
insert into test values (to_char(i_input_num) || i_input_vchar);
o_output_num := i_input_num + 1;
o_output_vchar := i_input_vchar || '1';
insert into test values (to_char(o_output_num) || o_output_vchar);
commit;
END;

Oracle JDBC call PL/SQL procedure with input parameter a table of records

I am trying to call the following pl/sql procedure from JDBC.
create or replace PACKAGE test AS
type testrec_r is record (
val1 number,
val2 varchar2(100)
);
type testarr_t is table of testrec_r index by binary_integer;
function test_func(i_data in testarr_t, o_sum out number, o_totallength out number) return number;
END test;
This is how I tried to invoke it, but without success:
StructDescriptor recDescriptor = StructDescriptor.createDescriptor("test.testrec_r", conn);
STRUCT[] RECORDS_ARRAY = new STRUCT[2];
for (int i = 0; i < 2; i++) {
STRUCT oracle_record = new STRUCT(recDescriptor, conn, new
Object[] {i, "test"});
RECORDS_ARRAY[i] = oracle_record;
}
CallableStatement stmt = conn.prepareCall("{ call TEST.TEST_FUNC(?, ?, ?) }");
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("TEST.TESTARR_T", conn);
ARRAY oracle_array = new ARRAY(arrayDescriptor, conn, RECORDS_ARRAY);
// Bind the input record
stmt.setArray(1, oracle_array);
stmt.registerOutParameter(2, Types.NUMERIC);
stmt.registerOutParameter(3, Types.NUMERIC);
stmt.executeUpdate();
double out1 = stmt.getDouble(2);
double out2 = stmt.getDouble(3);
return new Object[] { out1, out2 };
I just have read that oracle jdbc does not support pl/sql struct types. So, this fails with "invalid name pattern: test.testrec_r"
How can I call this procedure from Java? Ideally would be to only use a java libray/API, but as this seems almost imposible, which is the best workaround to wrap the pl/sql package in simple sql call and to invoke it?
P.S I am using Spring JDBCTemplate for database connection.
You cannot use PL/SQL types because they known to PL/SQL alone (since 12c this is no more strictly true - see UPD). Also any type created within a package is not visible by java directly.
You should create a SQL type at schema level. SQL types are visible to all and usable by all.
create or replace and compile java source named "ArrayOfRecTest" as
import java.io.*;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.driver.*;
public class ArrayOfRecTest
{
public static void passArrayOfRec() throws SQLException
{
Connection conn = new OracleDriver().defaultConnection();
StructDescriptor sd = StructDescriptor.createDescriptor("MYREC_TYPE", conn);
ArrayDescriptor ad = ArrayDescriptor.createDescriptor("MYRECARR_TYPE", conn);
STRUCT[] recarr = new STRUCT[2];
for (int i = 0; i < 2; i++) { recarr[i] = new STRUCT(sd, conn, new Object[] {i+1, "value " + (i+1)}); }
ARRAY oracle_array = new ARRAY(ad, conn, recarr);
CallableStatement stmt = conn.prepareCall("{ ? = call testpkg.showArrOfRec(?, ?, ?) }");
stmt.registerOutParameter(1, Types.INTEGER);
stmt.setObject(2, oracle_array);
stmt.registerOutParameter(3, Types.INTEGER);
stmt.registerOutParameter(4, Types.INTEGER);
stmt.execute();
int sizeofArr = stmt.getInt(1);
int total = stmt.getInt(3);
int totalLength = stmt.getInt(4);
System.out.println("passArrayOfRec(total,len)=(" + total + "," + totalLength + ") " + sizeofArr + " records were shown");
}
}
/
create or replace force type myrec_type as object( id number, value varchar2(100));
/
create or replace type myrecarr_type as table of myrec_type;
/
create or replace package testpkg as
procedure passArrayOfRec as language java name 'ArrayOfRecTest.passArrayOfRec()' ;
function showArrOfRec(ra myrecarr_type, total out number, totallength out number) return number;
end testpkg;
/
create or replace package body testpkg as
--OP stuff
type testrec_r is record (val1 number, val2 varchar2(100));
type testarr_t is table of testrec_r index by binary_integer;
function test_func(data in testarr_t, total out number, totallength out number) return number is
begin
<<for_each>> for i in data.first..data.last loop
dbms_output.put_line('data(' || i || ')[val1,val2]=[' || data(i).val1 || ',' || data(i).val2 || ']');
total := nvl(total,0) + data(i).val1;
totallength := nvl(totallength,0) + length(data(i).val2);
end loop for_each;
return data.count;
end test_func;
--end OP stuff
function showArrOfRec(ra myrecarr_type, total out number, totallength out number) return number is
data testarr_t;
begin
for i in ra.first..ra.last loop data(i).val1 := ra(i).id; data(i).val2 := ra(i).value; end loop;
return test_func(data, total, totalLength);
end showArrOfRec;
end testpkg;
/
exec testpkg.passArrayOfRec;
Output:
data(1)[val1,val2]=[1,value 1]
data(2)[val1,val2]=[2,value 2]
passArrayOfRec(total,len)=(3,14) 2 records were shown
UPD New in 12cR1: Using PL/SQL Types

Passing a parameter to a stored procedure

I would like to pass a parameter to this stored procedure:
ALTER PROCEDURE [USP_SelectProject]
-- Add the parameters for the stored procedure here
#ProjectNumber as int
AS
BEGIN
if #ProjectNumber is null
begin
select * from tbl_projects
end
else
begin
SELECT * from tbl_projects where ProjectID = #ProjectNumber
end
End
Here is the .net code
SqlConnection PTConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Project_Tracker"].ConnectionString);
SqlCommand PTCmd = new SqlCommand("USP_SelectProject", PTConn);
PTCmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter PTda = new SqlDataAdapter(PTCmd);
PTda.SelectCommand.Parameters["#ProjectNumber"].Value = DBNull.Value;
DataSet PTds = new DataSet();
PTda.Fill(PTds);
GridView1.DataSource = PTds;
GridView1.DataBind();
I am receiving the following error: An SqlParameter with ParameterName '#ProjectNumber' is not contained by this
You must Add() the parameter first.
SqlParameter p = PTda.SelectCommand.Parameters.Add("#ProjectNumber", DbType.Int);
p.Value = DBNull.Value;

ORA-01001 invalid cursor

I have an "ORA-01001 invalid cursor" issue I am not able to solve.
In our production environment, we have three application server and it's pointing the single Database(Oracle 10g).
I am receiving the "ora-01001 invalid cursor" error while calling the following procedure through the jdbc,
Procedure:
CREATE OR REPLACE
PROCEDURE "GET_CUSTOMER_DETAILS"(
p_ACC_NUM IN VARCHAR2 ,
o_PRODUCT_CODE OUT VARCHAR2 ,
o_PRODUCT_TYPE OUT VARCHAR2 ,
o_NATIONALITY OUT VARCHAR2 ,
o_CUSTOMER_CAT OUT VARCHAR2 ,
o_SERVICE_STATUS OUT VARCHAR2 ,
o_CURR_PLAN OUT VARCHAR2 ,
o_ERROR_CODE OUT NUMBER ,
o_ERROR_MSG OUT VARCHAR2 )
AS
v_count INT;
v_accNum VARCHAR2(50);
v_Product_Desc VARCHAR2(50);
v_IPhone_Status VARCHAR2(50);
v_BB_Status VARCHAR2(50);
v_now DATE;
BEGIN
o_CURR_PLAN := 0;
SELECT PRODUCT_DESC,
PRODUCT_NAME,
IPHONE_STATUS,
BB_STATUS,
PARTY_NATIONALITY,
CUSTOMER_CAT,
SERVICE_STATUS,
new_postpaid_flag
INTO v_Product_Desc,
o_PRODUCT_TYPE,
v_IPhone_Status,
v_BB_Status,
o_NATIONALITY,
o_CUSTOMER_CAT,
o_SERVICE_STATUS,
o_CURR_PLAN
FROM tbl_crm_custmaster
WHERE account_number = p_ACC_NUM
AND rownum = 1;
IF (v_Product_Desc = 'WS' AND v_IPhone_Status = 'N' AND v_BB_Status = 'N') THEN
o_PRODUCT_CODE := 'WP'; --General Prepaid
elsif (v_Product_Desc = 'WS' AND v_IPhone_Status = 'N' AND v_BB_Status = 'Y') THEN
o_PRODUCT_CODE := 'WB'; --BlackBerry Prepaid
elsif (v_Product_Desc = 'WS' AND v_IPhone_Status = 'Y' AND v_BB_Status = 'N') THEN
o_PRODUCT_CODE := 'WI'; --IPhone Prepaid
elsif (v_Product_Desc = 'WS' AND v_IPhone_Status = 'Y' AND v_BB_Status = 'Y') THEN
o_PRODUCT_CODE := 'WP'; --General Prepaid
elsif (v_Product_Desc = 'GS' AND v_IPhone_Status = 'N' AND v_BB_Status = 'N') THEN
o_PRODUCT_CODE := 'GP'; --General Postpaid
elsif (v_Product_Desc = 'GS' AND v_IPhone_Status = 'N' AND v_BB_Status = 'Y') THEN
o_PRODUCT_CODE := 'GB'; --BlackBerry Postpaid
elsif (v_Product_Desc = 'GS' AND v_IPhone_Status = 'Y' AND v_BB_Status = 'N') THEN
o_PRODUCT_CODE := 'GI'; --IPhone Postpaid
elsif (v_Product_Desc = 'GS' AND v_IPhone_Status = 'Y' AND v_BB_Status = 'Y') THEN
o_PRODUCT_CODE := 'GP'; --General Postpaid
elsif (v_Product_Desc = '2P' OR v_Product_Desc = '3P') THEN
o_PRODUCT_CODE := 'EL'; --Landline associated with E-Life
elsif (v_Product_Desc = 'VO') THEN
o_PRODUCT_CODE := 'GL'; --Landline Postpaid
elsif (v_Product_Desc = 'FN') THEN
o_PRODUCT_CODE := 'WL'; --Landline Prepaid
elsif (v_Product_Desc = 'HI') THEN
o_PRODUCT_CODE := 'IN'; --Landline Prepaid
elsif (v_Product_Desc = 'EV') THEN
o_PRODUCT_CODE := 'EV'; --Landline Prepaid
END IF;
o_ERROR_CODE := 0;
o_ERROR_MSG := 'SUCCESS';
EXCEPTION
WHEN NO_DATA_FOUND THEN
o_ERROR_CODE := -1;
o_ERROR_MSG := 'NO REOCRDS FOUND';
WHEN OTHERS THEN
o_ERROR_CODE := SQLCODE;
o_ERROR_MSG := SQLERRM;
END;
Java Code 1:
public void requestBegin(SCESession mySession) {
// TODO Auto-generated method stub
ITraceInfo trace = mySession.getTraceOutput();
UserDetails userDetails = (UserDetails) mySession.getProperty(EtisalatConstants.USER_DETAILS);
CallDetailsBean detailsBean=(CallDetailsBean) mySession.getProperty(EtisalatConstants.CALLER_DETAILS_BEAN_OBJECT);
DwhEtisalatMethods etisalatMethods=null;
HashMap<String, String> response = new HashMap<String, String>();
String hostErrResponse = "", hostErrCode = "";
EtaDbImpl dao = null;
try{
//Host Reporting Start Details
etisalatMethods=new DwhEtisalatMethods();
etisalatMethods.HostStartDetails(mySession, CommonMethod.generateUniqueId(), LoggingConstants.GET_CALLER_DETAILS_CRM, LoggingConstants.NOT_APPLICABLE, LoggingConstants.DATABASE);
dao = new EtaDbImpl();
response = dao.getCustomerDetails(userDetails.getPhoneNumber(), mySession);
trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG,"DB Success:");
hostErrCode = response.get(EtisalatDbConstants.ERROR_CODE);
hostErrResponse = response.get(EtisalatDbConstants.ERROR_MSG);
trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG,"ERROR_CODE:"+hostErrCode);
trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG,"ERROR_Response:"+hostErrResponse);
if(hostErrResponse.equalsIgnoreCase(EtisalatDbConstants.DB_SUCCESS_MSG) || hostErrCode.equalsIgnoreCase(EtisalatDbConstants.DB_SUCCESS_CODE)){
userDetails.setAccountNumber(response.get(EtisalatDbConstants.ACCOUNT_NUMBER));
//userDetails.setPhoneNumber(response.get(EtisalatDbConstants.PHONE_NUMBER));
userDetails.setProductType(response.get(EtisalatDbConstants.PRODUCT_TYPE));
userDetails.setProductCode(response.get(EtisalatDbConstants.PROD_CODE));
userDetails.setNationality(response.get(EtisalatDbConstants.NATIONALITY));
userDetails.setCustomerCategory(response.get(EtisalatDbConstants.CUSTOMER_CAT));
userDetails.setCurrPlan(response.get(EtisalatDbConstants.CURR_PLAN));
userDetails.setServiceStatus(response.get(EtisalatDbConstants.SERVICE_STATUS));
//Set in Project variable
mySession.getVariableField(IProjectVariables.APP_VARIABLES, IProjectVariables.APP_VARIABLES_FIELD_ACCOUNT_NO).setValue(userDetails.getAccountNumber());
mySession.getVariableField(IProjectVariables.APP_VARIABLES, IProjectVariables.APP_VARIABLES_FIELD_PRODUCT_CODE).setValue(userDetails.getProductCode());
mySession.getVariableField(IProjectVariables.APP_VARIABLES, IProjectVariables.APP_VARIABLES_FIELD_PRODUCT_TYPE).setValue(userDetails.getProductType());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_ACCT_NO).setValue(userDetails.getAccountNumber());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_CUSTOMER_CATEGORY).setValue(userDetails.getCustomerCategory());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_NATIONALITY).setValue(userDetails.getNationality());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_PRODUCT_CODE).setValue(userDetails.getProductCode());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_PRODUCT_TYPE).setValue(userDetails.getProductType());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_SERVICE_STATUS).setValue(userDetails.getServiceStatus());
mySession.getVariableField(IProjectVariables.GET_CRMCUST_MASTER, IProjectVariables.GET_CRMCUST_MASTER_FIELD_CURR_PLAN).setValue(userDetails.getCurrPlan());
detailsBean.setAuthenticated_Type(userDetails.getProductType());
detailsBean.setAuthenticated_number(userDetails.getAccountNumber());
mySession.getVariableField(IProjectVariables.FLAGS, IProjectVariables.FLAGS_FIELD_HOSTSERVICE_STATUS).setValue(EtisalatConstants.YES);
detailsBean.setCaller_authenticated(EtisalatConstants.REPORT_YES);
//Setting the customer segment for reporting purpose
detailsBean.setCustomer_segment(userDetails.getCustomerSegment());
//Setting the available products for the caller
//detailsBean.setProduct_category(userDetails.getProductType());
detailsBean.setProduct_category(userDetails.getProductCode());
detailsBean.setAccount_number(userDetails.getAccountNumber());
detailsBean.setAuthenticated_number(userDetails.getAccountNumber());
detailsBean.setAuthenticated_Type("AUTO");
}else if(hostErrResponse.equalsIgnoreCase(EtisalatDbConstants.DB_NO_REC_MSG) || hostErrCode.equalsIgnoreCase(EtisalatDbConstants.DB_NO_REC_CODE)){
mySession.getVariableField(IProjectVariables.FLAGS, IProjectVariables.FLAGS_FIELD_HOSTSERVICE_STATUS).setValue(EtisalatConstants.NO);
trace.writeln(ITraceInfo.TRACE_LEVEL_ERROR, "No Record Found for the account_number of '"+userDetails.getPhoneNumber()+"'");
}else{
throw new Exception(hostErrResponse); //Line No: 185
}
}catch (Exception e) {
// TODO Auto-generated catch block
detailsBean.setCall_end_reason(EtisalatConstants.CALLEND_REASON_DBDOWN);
mySession.getVariableField(IProjectVariables.FLAGS, IProjectVariables.FLAGS_FIELD_HOSTSERVICE_STATUS).setValue(EtisalatConstants.NO);
trace.writeln(ITraceInfo.TRACE_LEVEL_ERROR, "Exception : There is an issue while getting customer details "+e);
e.printStackTrace();
}finally{
mySession.setProperty(EtisalatConstants.USER_DETAILS, userDetails);
mySession.setProperty(EtisalatConstants.CALLER_DETAILS_BEAN_OBJECT, detailsBean);
//Host Reporting End Details
etisalatMethods.HostEndDetails(mySession, LoggingConstants.NOT_APPLICABLE, LoggingConstants.NOT_APPLICABLE, LoggingConstants.NOT_APPLICABLE, hostErrResponse, LoggingConstants.NOT_APPLICABLE);
response = null;
etisalatMethods=null;
hostErrResponse = null;
detailsBean = null;
trace = null;
userDetails = null;
dao = null;
}
super.requestBegin(mySession);
}
Java Code 2:
public HashMap<String, String> getCustomerDetails(String acctNo, SCESession mySession){
ITraceInfo trace = mySession.getTraceOutput();
dataSource = (BasicDataSource)mySession.getProperty(DATASRC_IVR_DB);
HashMap<String, String> returnhash = new HashMap<String, String>();
//trace.writeln(ITraceInfo.TRACE_LEVEL_INFO, "Account number :"+acctNo.substring(acctNo.length()-4) );
try
{
//logger.debug(callId+" The input is:"+hm);
start=System.currentTimeMillis();
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO, "Start Time of GET_CUSTOMER_DETAILS="+start);
con=dataSource.getConnection();
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO, "Data source connection established");
proc = con.prepareCall("{ call GET_CUSTOMER_DETAILS(?, ?, ?, ?, ?, ?, ?, ?, ?) }");
if(acctNo !=null && !acctNo.trim().isEmpty()){
proc.setString(1, acctNo);
}else{
proc.setNull(1, OracleTypes.VARCHAR);
}
proc.registerOutParameter(2, Types.VARCHAR);
proc.registerOutParameter(3, Types.VARCHAR);
proc.registerOutParameter(4, Types.VARCHAR);
proc.registerOutParameter(5, Types.VARCHAR);
proc.registerOutParameter(6, Types.VARCHAR);
proc.registerOutParameter(7, Types.VARCHAR);
proc.registerOutParameter(8, Types.INTEGER);
proc.registerOutParameter(9, Types.VARCHAR);
try {
if(!QueryTimeout.equalsIgnoreCase(NO))
proc.setQueryTimeout(Integer.parseInt(QueryTimeout));
else
proc.setQueryTimeout(_2s);
} catch (NumberFormatException e) {
proc.setQueryTimeout(_2s);
}
trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG,"Time out="+QueryTimeout);
proc.execute();
returnhash.put(ERROR_CODE, proc.getString(8));
returnhash.put(ERROR_MSG, proc.getString(9));
if(returnhash.get(ERROR_MSG).equalsIgnoreCase(DB_SUCCESS_MSG) || returnhash.get(ERROR_CODE).equalsIgnoreCase(DB_SUCCESS_CODE)){
returnhash.put(ACCOUNT_NUMBER, acctNo);
//returnhash.put(PHONE_NUMBER, rs.getString(2));
returnhash.put(PROD_CODE, proc.getString(2));
returnhash.put(PRODUCT_TYPE, proc.getString(3));
returnhash.put(NATIONALITY, proc.getString(4));
returnhash.put(CUSTOMER_CAT, proc.getString(5));
returnhash.put(SERVICE_STATUS, proc.getString(6));
returnhash.put(CURR_PLAN, proc.getString(7));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,ACCOUNT_NUMBER+":"+ acctNo);
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,PROD_CODE+":" + proc.getString(2));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,PRODUCT_TYPE+":" + proc.getString(3));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,NATIONALITY+":" + proc.getString(4));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,CUSTOMER_CAT+":" + proc.getString(5));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,SERVICE_STATUS+":" + proc.getString(6));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,CURR_PLAN+":" + proc.getString(7));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,ERROR_CODE+":"+proc.getString(8));
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO,ERROR_MSG+":"+proc.getString(9));
}else{
trace.writeln(ITraceInfo.TRACE_LEVEL_DEBUG, "No records found");
}
end=System.currentTimeMillis();
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO, "end Time of GET_CUSTOMER_DETAILS="+end);
trace.writeln(ITraceInfo.TRACE_LEVEL_INFO, "Total Time of GET_CUSTOMER_DETAILS="+(end-start)+"ms");
}
catch (SQLException e)
{
returnhash.put(ERROR_CODE, "03");
returnhash.put(ERROR_MSG, e.getMessage());
trace.writeln(ITraceInfo.TRACE_LEVEL_ERROR, "SQL Exception"+e);
e.printStackTrace();
}
finally{
try{
closeResult(rs);
closeCallableStmt(proc);
closeConnection(con);
}catch(SQLException e){
returnhash.put(ERROR_CODE, "03");
returnhash.put(ERROR_MSG, e.getMessage());
trace.writeln(ITraceInfo.TRACE_LEVEL_ERROR, "SQL Exception while closing the Connection "+e);
}
if(trace != null){
trace = null;
}
if(dataSource != null){
dataSource = null;
}
}
return returnhash;
}
Java code 1 method calls the Java Code 2 method.
In java Code 1, i'm processing the data what is received from the oracle.
In java code 2, i'm calling stored procedure.
I handled the sql exception in the procedure level. If any error in the procedure, the procedure returns the oracle error code and error message as a parameter. In the java Code 2, i'm receiving the oracle error code(1001) and store that in the hashmap, after that i'm checking whether the error code is equal to 0(success).So,it prints no reocrd log. In the java Code 1, i'm receiving the hashmap. From the hashmap,i take out the error code value. if the error code is not equavalent to 0 or -1, then i'm throwing the exception what i received from the oracle(printed in trace log and stack trace log).
Trace Log
12/06/2013 06:26:35:063 INFO - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : Start Time of GET_CUSTOMER_DETAILS=1371003995063
12/06/2013 06:26:35:065 INFO - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : Data source connection established
12/06/2013 06:26:35:065 DEBUG - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : Time out=2
12/06/2013 06:26:35:067 DEBUG - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : No records found
12/06/2013 06:26:35:067 INFO - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : end Time of GET_CUSTOMER_DETAILS=1371003995067
12/06/2013 06:26:35:067 INFO - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : Total Time of GET_CUSTOMER_DETAILS=4ms
12/06/2013 06:26:35:067 DEBUG - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : DB Success:
12/06/2013 06:26:35:067 DEBUG - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : ERROR_CODE:-1001
12/06/2013 06:26:35:067 DEBUG - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : ERROR_Response:ORA-01001: invalid cursor
12/06/2013 06:26:35:067 ERROR - EC2E4987556A7FF7DA6DEE8EEE9843FC.jvm2:/ETA_MAIN : Exception : There is an issue while getting customer details java.lang.Exception: ORA-01001: invalid cursor
Stack Trace Log:
java.lang.Exception: ORA-01001: invalid cursor
at flow.DB_GetCRM_CustMaster.requestBegin(DB_GetCRM_CustMaster.java:185)
at com.avaya.sce.runtime.AppServlet.processRequest(AppServlet.java:81)
at com.avaya.sce.runtime.SCEServlet.requestHandler(SCEServlet.java:282)
at com.avaya.sce.runtime.SCEServlet.doPost(SCEServlet.java:189)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at com.avaya.sce.runtime.SCEServlet.forward(SCEServlet.java:1303)
at com.avaya.sce.runtime.Data.evaluateActions(Data.java:211)
at flow.DB_GetCallerProfileDetails.executeDataActions(DB_GetCallerProfileDetails.java:94)
I couldn't reproduce this issue in SQLPlus, it only happens from jdbc calls from the application server 2 and application server 3, and repeating the same call usually works (but sometimes fails couple of times before succeeding). I have not used any cursor in the procedure. Please help me on this issue.
Maybe types are incorrect.. can You change signature to something like that:
CREATE OR REPLACE PROCEDURE "GET_CUSTOMER_DETAILS"(
p_ACC_NUM IN VARCHAR2 ,
o_PRODUCT_CODE OUT VARCHAR2 ,
o_PRODUCT_TYPE OUT tbl_crm_custmaster.PRODUCT_NAME%type,
o_NATIONALITY OUT tbl_crm_custmaster.PARTY_NATIONALITY%type ,
o_CUSTOMER_CAT OUT tbl_crm_custmaster.CUSTOMER_CAT%type ,
o_SERVICE_STATUS OUT tbl_crm_custmaster.SERVICE_STATUS%type ,
o_CURR_PLAN OUT tbl_crm_custmaster.new_postpaid_flag%type,
o_ERROR_CODE OUT NUMBER ,
o_ERROR_MSG OUT VARCHAR2 ) AS
v_count INT;
v_accNum VARCHAR2(50);
v_Product_Desc tbl_crm_custmaster.PRODUCT_DESC%type,
v_IPhone_Status tbl_crm_custmaster.IPHONE_STATUS%type;
v_BB_Status tbl_crm_custmaster.BB_STATUS%type;
v_now DATE;

Using ODP.NET to get a RECORD from PL/SQL function, without touching PL/SQL code

The title is pretty-self-explanatory: from a C# application, using ODP.NET, I'm trying to call a PL/SQL function that returns not a simple value, but a record.
Unfortunately, I'm not authorized to add or change the PL/SQL code, so attempting to wrap the function in another function that returns a different type is not an option for me.
Here is a simplified example...
PL/SQL:
CREATE OR REPLACE PACKAGE FOO_PACKAGE AS
TYPE FOO_RECORD IS RECORD (
BAR VARCHAR2(50),
BAZ VARCHAR2(50)
);
FUNCTION FOO_FUNCTION RETURN FOO_RECORD;
END;
/
CREATE OR REPLACE PACKAGE BODY FOO_PACKAGE AS
FUNCTION FOO_FUNCTION RETURN FOO_RECORD AS
R FOO_RECORD;
BEGIN
R.BAR := 'Hello bar!';
R.BAZ := 'Hello baz!';
RETURN R;
END;
END;
/
C#:
The first thing I tried was the most direct approach, but I'm at a loss how to bind the return parameter...
using (var conn = new OracleConnection(connection_string)) {
conn.Open();
using (var tran = conn.BeginTransaction()) {
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "FOO_PACKAGE.FOO_FUNCTION";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(
null,
/* What to use here? */,
ParameterDirection.ReturnValue
);
cmd.ExecuteNonQuery();
}
}
}
I have also tried some "roundabout" approaches, but they all throw exceptions:
cmd.CommandText = "SELECT * FROM FOO_PACKAGE.FOO_FUNCTION";
cmd.ExecuteReader(); // ORA-00942: table or view does not exist
cmd.CommandText = "SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL";
cmd.ExecuteReader(); // ORA-00902: invalid datatype
cmd.CommandText = "SELECT BAR, BAZ FROM (SELECT FOO_PACKAGE.FOO_FUNCTION FROM DUAL)";
cmd.ExecuteReader(); // ORA-00904: "BAZ": invalid identifier
You need anonymous PL/SQL block to convert function result to another representation:
declare
vFooRes FOO_PACKAGE.FOO_RECORD;
vRes sys_refcursor;
begin
vFooRes := FOO_PACKAGE.FOO_FUNCTION;
open vRes for select vFooRes.BAR, vFooRes.BAZ from dual;
--:result := vRes;
end;
SQLfiddle
And execute it instead of calling stored procedure:
cmd.CommandText = "declare\n" +
" vFooRes FOO_PACKAGE.FOO_RECORD;\n" +
"begin\n" +
" vFooRes := FOO_PACKAGE.FOO_FUNCTION;\n" +
" open :result for select vFooRes.BAR, vFooRes.BAZ from dual;\n" +
"end;";
OracleParameter p = cmd.Parameters.Add(
"result",
OracleDbType.RefCursor,
DBNull.Value,
ParameterDirection.Output
);
cmd.ExecuteNonQuery();
After executing cmd you get cursor in result parameter which can be used to fill dataset:
var adapter = new OracleDataAdapter(cmd);
var data = new DataSet("FooDataSet");
adapter.Fill(data, "result", (OracleRefCursor)(p.Value));

Resources