ORA-01001 invalid cursor - oracle
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;
Related
How to return two types in pl/sql oracle
How to return two types in pl/sql oracle? return number -- here I tell than function reurns number, but i want to return number and string when an exception is thrown is prPrice number; -- product price curFrom number; -- price pgcount number := 0; -- product count noProductsOnDate EXCEPTION; wrongCurrency EXCEPTION; begin SELECT COUNT(*) INTO pgcount from Products pr, Outgoing outg, Incoming inc where pr.PROD_ID = outg.PROD_ID and pr.PROD_ID = inc.PROD_ID and inc.inc_date > d Having sum(inc.quantity) > sum(outg.quantity); if pgcount = 0 or pgcount is null then raise noProductsOnDate; END IF; if curTo > 2 OR curTo < 1 then raise wrongCurrency; end if; If curTo = 1 then curFrom := 2; Elsif curTo = 2 then curFrom := 1; END IF; select pric.Value*cour.value into prPrice from Prices pric, Cources cour where p = pric.prod_id and pric.DAYFROM <= d and (pric.DAYTO >= d or pric.DAYTO is null) and cour.cur_idto = curTo and cour.cur_idfrom = curFrom; return prPrice; -- here i wanna return number exception when noProductsOnDate then return '1q'; -- here i wanna return string (error message) when wrongCurrency then return '2q'; -- here i wanna return string (error message) end; I can't return string in exception, because function return number Maybe I doing something wrong, Please, tell me how can I return several data types from one function, maybe I should do everything differently, but I don't understand how to do it ((
You can't do it that way, but can another way around - declare function to return varchar2. Then, in your code, you can create function ... return varchar2 is begin ... do whatever you're doing return to_char(poPrice); exception when ... then return '1q'; end;
I write my functions often in this form: return 0 in case of success return a positive number in case of a warning (often not used) return a negative number in case of an error And I use out parameters for the function results, in your case the price and/or a message. Something along the lines of: CREATE OR REPLACE FUNCTION my_function(vi_date IN DATE, vo_price OUT NUMBER, vo_msg OUT VARCHAR) RETURN INTEGER IS BEGIN ... IF pgcount = 0 OR pgcount IS NULL THEN vo_msg := 'No products on that date.'; RETURN -20001; -- return custom error code END IF; ... IF vo_price < 0 THEN vo_msg := 'Price is negative. Calculation my be wrong.'; RETURN 1; -- return warning flag (positive number) ELSE RETURN 0; -- means success END IF; EXCEPTION WHEN OTHERS THEN -- Error. Return negative number. SQLCODE is always the negative ORA code -- except for ORA-1403 which is strangely SQLCODE 100 instead vo_msg := SQLERRM; RETURN CASE WHEN SQLCODE = 100 THEN -1403 ELSE SQLCODE END; END my_function; Then call it like this: DECLARE v_code INTEGER; v_price NUMBER (10,2); v_msg VARCHAR(1000); BEGIN v_code := my_function(DATE '2022-09-29', v_price, v_msg); IF v_code >= 0 THEN DBMS_OUTPUT.PUT_LINE('The price is: ' || v_price); END IF; IF v_code <> 0 THEN DBMS_OUTPUT.PUT_LINE('Message: ' || v_msg); END IF; END;
Update: Function Error: PLS-00306: wrong number or types of arguments in call to 'get_bus_result_attribute'
I just think the problem of issue and change the function-to-function logic design. Then, the error as mentioned the function (get_result_attribute) - PLS-00306: wrong number or types of arguments in call to 'get_result_attribute'. May I know the function "get_result_attribute" problem in which part? Coding for the bus station system. FUNCTION get_bus_result_attribute (iv_result_name varchar2, iv_result_key varchar2, iv_result_attribute varchar2) --define the parameter to get the "sql_result" script result RETURN varchar2 IS sql_result varchar2(500); sql_return varchar2(500); BEGIN sql_result := 'SELECT ' || iv_result_attribute || ' FROM MyTable a, MyTable b WHERE a.bus_value_set_id = b.bus_value_set_id AND b.bus_value_set_name = iv_result_name AND a.enabled_flag = ''Y'' AND a.bus_value = iv_result_key AND iv_result_name = get_bus_code (v_bus) AND iv_result_key = get_bus_name(v_group) AND iv_result_key = iv_result_attribute'; EXECUTE IMMEDIATE sql_result INTO sql_return; --get the "sql_result" script result return sql_return; exception when others then return ''; end get_bus_result_attribute; FUNCTION get_bus_code (v_bus varchar2) RETURN VARCHAR2 IS v_get_bus_code_result VARCHAR2(20) ; BEGIN SELECT busa.bus_code INTO v_get_bus_code_result FROM tbl_bus_code busa, tbl_bus_line busb WHERE busa.bus_code_set_id = busb.bus_code_set_id AND busb.bus_line_set_name = 'HK_BUS_CODE' AND busa.enabled_flag = 'Y' AND (busa.attribute4 = 'Y' OR busa.attribute5 = 'Y') AND busa.BUS_VALUE = v_bus; RETURN v_get_bus_code_result; RETURN get_result_attribute('BUS_LINES', v_bus, 'attribute1'); /*BUS_GP*/ EXCEPTION WHEN OTHERS THEN RETURN ''; END get_bus_code; FUNCTION get_bus_name(v_group VARCHAR2) --define the parameter and enter the value in the function 'get_bus_result_attribute' RETURN VARCHAR2 IS v_get_bus_div_result VARCHAR2(20) ; BEGIN SELECT DISTINCT CASE busa.bus_code --Bus code WHEN '52' THEN '52X' WHEN '58P' THEN '58' WHEN 'K1' THEN 'K1C' WHEN '40' THEN '40X' WHEN '6' THEN '6X' WHEN '7' THEN '7' WHEN '58M' THEN '58' ELSE '' END bus_code --Bus code INTO v_get_bus_div_result FROM tbl_bus_code busa, tbl_bus_line busb WHERE busa.bus_code_set_id = busb.bus_code_set_id AND busb.bus_line_set_name = 'HK_BUS_LINES' AND busa.enabled_flag = 'Y' AND (busa.attribute4 = 'Y' OR busa.attribute5 = 'Y') AND busa.bus_code NOT IN ('INACTIVE', 'XXX') AND get_bus_code(busa.BUS_VALUE) = v_group RETURN get_result_attribute('BUS_GROUP', v_group, 'attribute2'); --bus_group_dir EXCEPTION WHEN OTHERS THEN RETURN ''; END get_bus_name; FUNCTION BUS_DOC_TEXT (N_ID NUMBER, N_HEAD_ID NUMBER) RETURN VARCHAR2 IS v_bus_doc_text VARCHAR2(150); BEGIN SELECT 'BUS\' || get_bus_result_attribute(abc.attribute14) || '\' || abc.attribute14 || '\' || abc.segment1 INTO v_bus_doc_text FROM my_table_c abc WHERE abc.ORG_ID = N_ID -- parameter AND abc.bus_id = N_HEADER_ID; -- parameter END; RETURN v_bus_doc_text ; END; END;
SQL state [99999]; error code [17004]; Type de colonne non valide: 1111
I have this call to PL/SQL function FUNCTION F_IsDemandeDeLitFromHosp(i_NoMvtHosp IN MVTHOSP.NOMVTHOSP%TYPE )RETURN BOOLEAN IS v_Found NUMBER := 0; BEGIN BEGIN SELECT COUNT(1) INTO v_Found FROM ICSF.T_DEMANDE_LIT D, MVTUS U, MVTHOSP H WHERE H.NOMVTHOSP = i_NoMvtHosp AND H.NOMVTHOSP = U.NOMVTHOSP AND U.NOMVTUS = D.NOMVTUS AND U.RANG <> '0000000000' AND H.RANG = '0000100000' AND NVL (D.ETAT, ' ') <> 'X' AND NVL (U.ETAT, ' ') <> 'X' AND NVL (H.ETAT, ' ') <> 'X' AND ROWNUM = 1; EXCEPTION WHEN OTHERS THEN RETURN FALSE; END; IF v_Found > 0 THEN RETURN TRUE; ELSE RETURN FALSE; END IF; END F_IsDemandeDeLitFromHosp; I try to write a service to get the boolean in return. i_NoMvtHosp is a CHAR(10 BYTE) and here is the call of my function: #Override public DemandeDeLitFromHospit isDemandeDelitFromHosp(String noMvtHosp) { final ProcedureRequest request = new ProcedureRequest(PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getPackageName(), PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getMethodeName()); request.addInParam("i_NoMvtHosp", noMvtHosp); DemandeDeLitFromHospit demande = new DemandeDeLitFromHospit(); demande.setIsDemandeDeLitFromHosp((Boolean)callFunction(request, new CallableStatementCallback<Boolean>() { public Boolean doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException { cs.execute(); return Boolean.valueOf(cs.getResultSet().toString()); } })); return demande; } And I've got this error: org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL []; SQL state [99999]; error code [17004]; Type de colonne non valide: 1111; nested exception is java.sql.SQLException: Type de colonne non valide: 1111 at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1032) at fr.mckesson.framework.persistence.plsql.AbstractProcedureDao.callFunction(AbstractProcedureDao.java:317) at fr.mckesson.business.venue.clinique.evenement.dao.implementation.DemandeLitDAO.isDemandeDelitFromHosp(DemandeLitDAO.java:42) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) Where am i wrong ?
Your code is failing on error code [17004]; invalid column type: 1111 . This error happens because your code uses a datatype which JDBC doesn't recognise. This is probably because your function returns BOOLEAN. Boolean is not a valid SQL datatype. You wouldn't be able to call that a function in a straightforward Oracle SQL query either. It is true that JDBC does provide a mapping of bit to Java boolean and Boolean, but that will only work for database products which support that non-standard datatype, and Oracle isn't one of them.
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
Exception block in PLSQL exiting the block
I am using the following code block to update my front end segment. But when i am compiling this DECLARE p_person_id NUMBER := NULL; p_business_group_id NUMBER; p_id_flex_num NUMBER; ------------------ p_analysis_criteria_id NUMBER := NULL; p_person_analysis_id NUMBER := NULL; p_per_object_version_number NUMBER := NULL; v_err VARCHAR2 (1000) := NULL; p_medical_id VARCHAR2 (100) := NULL; BEGIN FOR i IN (SELECT * FROM xx_hr_upload_master_data_new WHERE person_id IS NOT NULL AND business_group_id IS NOT NULL AND medical_id IS NOT NULL) LOOP p_id_flex_num := 50530; BEGIN SELECT sv.segment1, NVL (sit.object_version_number, 1), sit.analysis_criteria_id, MAX (sit.person_analysis_id) INTO p_medical_id, p_per_object_version_number, p_analysis_criteria_id, p_person_analysis_id FROM fnd_id_flex_structures_tl sttl, fnd_id_flex_structures st, per_person_analyses sit, per_analysis_criteria sv WHERE sttl.id_flex_structure_name = 'ISPs Medical Data' AND sttl.LANGUAGE = USERENV ('LANG') AND st.id_flex_code = sttl.id_flex_code AND st.id_flex_num = sttl.id_flex_num AND st.id_flex_num = sit.id_flex_num AND st.id_flex_num = sv.id_flex_num AND sit.analysis_criteria_id = sv.analysis_criteria_id AND sit.person_id = i.person_id --and sv.SEGMENT1 = '4602001140' GROUP BY sv.segment1, NVL (sit.object_version_number, 1), sit.analysis_criteria_id; EXCEPTION WHEN OTHERS THEN p_medical_id := NULL; p_per_object_version_number := 1; p_person_analysis_id := NULL; p_analysis_criteria_id := NULL; p_person_analysis_id := NULL; p_per_object_version_number := NULL; p_person_id := NULL; END; BEGIN ------------------------------------------------ IF (p_medical_id IS NULL AND p_analysis_criteria_id IS NULL) THEN -- create a new record in the SIT (Special Information Type)table . p_person_id := i.person_id; p_medical_id := TO_CHAR (i.medical_id); ----------------------------- hr_sit_api.create_sit (p_validate => FALSE, p_person_id => p_person_id, p_business_group_id => i.business_group_id, p_id_flex_num => p_id_flex_num, p_effective_date => TRUNC (SYSDATE), p_date_from => TRUNC (SYSDATE), p_segment1 => p_medical_id, p_analysis_criteria_id => p_analysis_criteria_id, p_person_analysis_id => p_person_analysis_id, p_pea_object_version_number => p_per_object_version_number ); ELSE -- employee has previous Billing_Acc_Num then update that number in the SIT table . hr_sit_api.update_sit (p_validate => FALSE, p_person_analysis_id => p_person_analysis_id, p_pea_object_version_number => p_per_object_version_number, p_date_from => TRUNC (SYSDATE), p_segment1 => p_medical_id, p_analysis_criteria_id => p_analysis_criteria_id ); END IF; UPDATE xx_hr_upload_master_data_new xx SET xx.error_msg = 'Done', xx.emp_data = 'Done' WHERE xx.business_group_id = i.business_group_id AND xx.employee_number = i.employee_number; EXCEPTION WHEN OTHERS THEN p_analysis_criteria_id := NULL; p_person_analysis_id := NULL; p_per_object_version_number := NULL; p_person_id := NULL; p_medical_id := NULL; v_err := NULL; v_err := SQLERRM; UPDATE xx_hr_upload_master_data_new xx SET xx.error_msg = v_err WHERE xx.business_group_id = i.business_group_id AND xx.employee_number = i.employee_number; END; END LOOP; COMMIT; END; Now when the select query is not fetching anything, the exception block is entered where all the variables are initiated to null. I want that after this the begin where the create api is called inside the condition IF (p_medical_id IS NULL AND p_analysis_criteria_id IS NULL) should be entered. But this is not happening and the program exits after this exception block after entering the exception block.
A hint might be: The first select will not raise any exception if it gets no result. If it gets no result then the for-loop just won't be entered, so the only thing that will happen is the commit. (The select inside the for-loop will raise an exception if it gets 0 rows or more than 1 row. The reason is 'select ... into ...': When using 'into' the select must return exact 1 row.)