I'm having trouble correctly displaying the results of my procedure. When I execute the procedure that I created. The output should be 'FALSE' since DonorID: 303 has IDStatus = 20 and Paymonths = 0. However, I am getting 'TRUE.' Can someone please help?
CREATE OR replace PROCEDURE ddpay_sp (donorid IN NUMBER,
completed_pledge OUT BOOLEAN)
IS
CURSOR donor_cur IS
SELECT idstatus,
paymonths
FROM dd_pledge
WHERE iddonor = donorid;
p_idstatus NUMBER(2);
p_paymonths NUMBER(3);
BEGIN
OPEN donor_cur;
LOOP
FETCH donor_cur
INTO p_idstatus,
p_paymonths;
EXIT WHEN donor_cur%NOTFOUND;
IF p_idstatus = 20 AND p_paymonths = 0 THEN
completed_pledge := FALSE;
ELSE
completed_pledge := TRUE;
EXIT;
END IF;
END LOOP;
CLOSE donor_cur;
END ddpay_sp;
DECLARE
status BOOLEAN;
BEGIN
ddpay_sp(303, status);
IF status = TRUE THEN
dbms_output.put_line('TRUE');
ELSE
dbms_output.put_line('FALSE');
END IF;
END;
If you have multiple rows in your table that match iddonor = donorid, Oracle will loop through them until it finds one that doesn't match your p_idstatus = 20 AND p_paymonths = 0 condition and then exit from the loop with true, it will only return 'FALSE' if they all match on the second condition. If you have no rows that match iddonor = donorid, then your check will show 'FALSE' Demo
You need to be clear what should happen when there are multiple rows in dd_pledge which have the input iddonor value. E.g. if you wish for it to return false if there are any matching rows which have idstatus=20 and paymonths=0 then you could make the loop exit on this condition instead:
CREATE OR replace PROCEDURE ddpay_sp (donorid IN NUMBER,
completed_pledge OUT BOOLEAN)
IS
CURSOR donor_cur IS
SELECT idstatus,
paymonths
FROM dd_pledge
WHERE iddonor = donorid;
p_idstatus NUMBER(2);
p_paymonths NUMBER(3);
BEGIN
OPEN donor_cur;
LOOP
FETCH donor_cur
INTO p_idstatus,
p_paymonths;
EXIT WHEN donor_cur%NOTFOUND;
IF p_idstatus = 20 AND p_paymonths = 0 THEN
completed_pledge := FALSE;
EXIT;
ELSE
completed_pledge := TRUE;
END IF;
END LOOP;
CLOSE donor_cur;
END ddpay_sp;
/
Demo showing the difference due to exit placement
Related
I am trying to implement a validation on an application item in APEX 5.0. I am using a PL/SQL function returning a boolean
begin
if exists (select id_referencia
from items
where id_referencia = :P2_REFERENCIA)
then
return true;
else
return false;
end if;
end;
When I submit my page, I get the following error
ORA-06550: line 2, column 4: PLS-00204: function or pseudo-column
'EXISTS' may be used inside a SQL statement only ORA-06550: line 2,
column 1: PL/SQL: Statement ignored
if exists isn't valid PL/SQL syntax.
You could do a count(*) instead
declare
l_cnt integer;
begin
select count(*)
into l_cnt
from items
where id_referencia = :P2_REFERENCIA;
if( l_cnt >= 1 )
then
return true;
else
return false;
end if;
end;
If you really wanted to do an exists, you'd do something like this. I don't know why you'd want to do this assuming that id_referencia is the primary key of the table. But you could
declare
l_exists integer;
begin
begin
select 1
into l_exists
from dual
where exists( select 1
from items
where id_referencia = :P2_REFERENCIA );
exception
when no_data_found
then
l_exists := 0;
end;
if( l_exists = 1 )
then
return true;
else
return false;
end if;
end;
If you want to use EXISTS in a PL/SQL function returning BOOLEAN,try this
DECLARE
v_exist NUMBER;
BEGIN
SELECT 1
INTO v_exist
FROM DUAL WHERE EXISTS (select id_referencia
from items
where id_referencia = :P2_REFERENCIA)
IF v_exist IS NOT NULL
THEN
RETURN true;
ELSE
RETURN false;
END IF;
END;
I want my function to display 'Empty Invoice Found!' Or 'Invoice Not Found' error messages.
But when I select the data with error(doesnt exist in the table), it return 'no rows selected'. Please guide me with the correct way to SELECT.
SET ECHO ON;
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION totalInvoiceAmount(InvoiceNo IN INVOICE_ITEM.InvoiceNumber%TYPE)
RETURN NUMBER IS
TotalCost NUMBER(20);
CURSOR X_RECORD IS SELECT * FROM INVOICE_ITEM;
CURSOR Y_RECORD IS SELECT * FROM INVOICE_ITEM;
tempCost NUMBER:=0;
InvoiceCheck BOOLEAN:=FALSE;
InvoiceEmpty BOOLEAN:=TRUE;
BEGIN
FOR Record IN X_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo THEN
InvoiceCheck:=TRUE;
EXIT;
ELSE
InvoiceCheck:=FALSE;
END IF;
END LOOP;
FOR Record IN Y_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo AND InvoiceCheck=FALSE THEN
InvoiceEmpty:=TRUE;
EXIT;
ELSE
InvoiceEmpty:=FALSE;
END IF;
END LOOP;
IF InvoiceCheck=FALSE AND InvoiceEmpty=FALSE THEN
DBMS_OUTPUT.PUT_LINE('Invoice Not Found!');
RETURN -1;
ELSIF InvoiceCheck=FALSE AND InvoiceEmpty=TRUE THEN
DBMS_OUTPUT.PUT_LINE('Empty Invoice Found!');
RETURN 0;
ELSE
FOR Record IN X_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo THEN
tempCost:=tempCost+(Record.UnitPrice*Record.Quantity);
END IF;
END LOOP;
TotalCost:=tempCost;
RETURN TotalCost;
END IF;
END;
/
SELECT invoicenumber,totalInvoiceAmount(invoicenumber) AS "Total Cost" FROM INVOICE_ITEM Where invoicenumber=2011011;
SELECT invoicenumber,totalInvoiceAmount(invoicenumber) AS "Total Cost" FROM INVOICE_ITEM where invoicenumber=2011010;
The messages you want come from a function which you are calling in a SELECT statement. So if that SELECT returns no rows there are are no rows which can be used to call that function.
I'm afraid it's not clear what you're trying to achieve, but whatever it is you need a different approach. Having said which I suggest something like this might be give you what you want (in a more orthodox and more efficient fashion):
SELECT invoicenumber,
sum(UnitPrice*Quantity) AS "Total Cost"
FROM INVOICE_ITEM
where invoicenumber=2011010
group by InvoiceNumber;
SET ECHO ON;
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION totalInvoiceAmount(InvoiceNo IN INVOICE_ITEM.InvoiceNumber%TYPE)
RETURN NUMBER IS
TotalCost NUMBER(20);
invoice_not_found EXCEPTION ;
empty_invoice_found EXCEPTION ;
CURSOR X_RECORD IS SELECT * FROM INVOICE_ITEM;
CURSOR Y_RECORD IS SELECT * FROM INVOICE_ITEM;
tempCost NUMBER:=0;
InvoiceCheck BOOLEAN:=FALSE;
InvoiceEmpty BOOLEAN:=TRUE;
BEGIN
FOR Record IN X_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo THEN
InvoiceCheck:=TRUE;
EXIT;
ELSE
InvoiceCheck:=FALSE;
END IF;
END LOOP;
FOR Record IN Y_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo AND InvoiceCheck=FALSE THEN
InvoiceEmpty:=TRUE;
EXIT;
ELSE
InvoiceEmpty:=FALSE;
END IF;
END LOOP;
IF InvoiceCheck=FALSE AND InvoiceEmpty=FALSE THEN
--DBMS_OUTPUT.PUT_LINE('Invoice Not Found!');
RAISE invoice_not_found;
--RETURN -1;
ELSIF InvoiceCheck=FALSE AND InvoiceEmpty=TRUE THEN
--DBMS_OUTPUT.PUT_LINE('Empty Invoice Found!');
RAISE empty_invoice_found
RETURN 0;
ELSE
FOR Record IN X_RECORD LOOP
IF Record.InvoiceNumber = InvoiceNo THEN
tempCost:=tempCost+(Record.UnitPrice*Record.Quantity);
END IF;
END LOOP;
TotalCost:=tempCost;
RETURN TotalCost;
END IF;
EXCEPTION
when invoice_not_found then
DBMS_OUTPUT.PUT_LINE('Invoice Not Found!');
raise -1;
when empty_invoice_found then
DBMS_OUTPUT.PUT_LINE('Empty Invoice Found!');
raise 0;
END;
You can catch it in an exception and handle it accordingly , let me know if it works
I am using the following stored procedure for returning an incremented key value for a specific keyword. It takes an optional parameter of Y or N to determine if the result should be prefixed by another value.
create or replace
PROCEDURE "ASGETPRIMARYKEY"
(
p_ObjectName IN LASTPRIMARYKEY.OBJECTNAME%type ,
p_PrimaryKey OUT LASTPRIMARYKEY.NEXTKEY%type,
useSitePrefix IN NVARCHAR2 Default 'Y'
)
AS
v_transcount NUMBER := 1;
v_sys_error NUMBER := 0;
v_SitePrefix NVARCHAR2(4000);
v_LastPrimaryKey NUMBER(10,0);
-- Error Handling Variables
v_LocalTran NUMBER(1,0);
v_Error NUMBER(10,0);
BEGIN
NULL/*TODO:SET XACT_ABORT ON*/;
NULL/*TODO:SET NOCOUNT ON*/;
-- STEP 0: Start the transaction
-- If procedure doesn't need to begin a transaction this can be set to 0
IF v_transcount > 0 THEN
v_LocalTran := 0;
ELSE
v_LocalTran := 1;
END IF;
IF v_LocalTran = 1 THEN
SET TRANSACTION READ WRITE;
v_transcount := v_transcount + 1;
END IF;
-- STEP 1: Get #SitePrefix
SELECT settingtext
INTO v_SitePrefix
FROM systemsetting
WHERE settingdescription = 'Site Id Prefix';
-- Check if there were any errors
v_Error := v_sys_error;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1a)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 1b: Check SitePrefix exists
-- Rollback the transaction if SitePrefix doesn't exist in systemsetting
IF v_SitePrefix IS NULL THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1b)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
BEGIN
-- STEP 2: Set NextKey for requested ObjectName
UPDATE LastPrimaryKey
SET NextKey = (NextKey + 1)
WHERE objectname = p_ObjectName;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
BEGIN
-- Check if there were any errors
v_Error := v_sys_error;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(2)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 3: Set NextKey for for requested ObjectName
SELECT NextKey - 1
INTO v_LastPrimaryKey
FROM LastPrimaryKey
WHERE objectname = p_ObjectName;
BEGIN
-- Check if there were any errors
v_Error := v_sys_error;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(3)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 4: Check SitePrefix exists
-- Rollback the transaction if SitePrefix doesn't exist in systemsetting
IF v_LastPrimaryKey IS NULL THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(4)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 5: Set #p_PrimaryKey by adding prefix
IF useSitePrefix = 'y' THEN
p_PrimaryKey := (CAST(v_SitePrefix || CAST(v_LastPrimaryKey AS NVARCHAR2) AS NUMBER));
ELSE
p_PrimaryKey := v_lastprimarykey;
END IF;
-- Check if there were any errors
v_Error := v_sys_error;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(5)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 6: If we reach this point, the commands completed successfully
-- Commit the transaction....
-- Normal exit
IF v_LocalTran = 1 THEN
COMMIT;
v_transcount := v_transcount - 1;
END IF;
-- Error Exit
<<ErrExit>>
IF v_LocalTran = 1 THEN
ROLLBACK;
v_transcount := v_transcount - 1;
END IF;
END;
The stored proc is called from a enterpriselibrary using the following vb code:
Dim sqlCommand As String = "asGetPrimaryKey"
Dim _db As Database = EnterpriseLibraryContainer.Current.GetInstance(Of Database)(ASDBMSS.clsDBMSS.ConnectionStringName)
Dim DbCommand As System.Data.Common.DbCommand = _db.GetStoredProcCommand(sqlCommand)
' Add primary keys to command wrapper.
_db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)
If pbIgnoreSiteIndex Then
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
Else
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
End If
_db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)
_db.ExecuteNonQuery(DbCommand)
Dim _result As String = _db.GetParameterValue(DbCommand, "p_PrimaryKey").ToString
lcl_NextKey = CInt(_result)
result = 1
The problem arrises when I pass the optional parameter in.
If I skip the line with the optional parameter, it works fine.
If I use SQL server instead of Oracle, it works fine.
If I pass the parameter and use Oracle I get the following error message:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 1
Any suggestions?
Change v_LastPrimaryKey from number(10,0) to same as p_PrimaryKey OUT LASTPRIMARYKEY.NEXTKEY%type,
Secondly, you are passing Y or N but inside code comparing y. So flow is always going in "else", where you are not using cast.
Hope that helps.
Cheers
V
I have found the problem!
SQL server does not care in what order the parameters are passed as long as the names match. Oracle it seems, does.
I changed the order in which they are called to this:
_db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)
_db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)
If pbIgnoreSiteIndex Then
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
Else
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
End If
_db.ExecuteNonQuery(DbCommand)
And it now works without error
I am getting following error for the stored procedure and not able to understand the issue (must be from db side) While googling, I found similar issues but couldn't get the solution. Can any one help me please find the error in PROCEDURE ??
Error :-
18:58:50,281 ERROR [STDERR] java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'SP_DIST_RETAILER_REMAP'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Stored Prodedure(SP_DIST_RETAILER_REMAP) :-
CREATE OR REPLACE PROCEDURE SMAPRD02.SP_DIST_RETAILER_REMAP (
i_old_dist_code IN VARCHAR2,
i_new_dist_code IN VARCHAR2,
i_territory_remapping IN NUMBER,
i_remapping_reason IN VARCHAR2,
i_trans_doneby_rolename IN VARCHAR2,
i_trans_doneby_id IN NUMBER,
i_trans_dist_rolename IN VARCHAR2,
i_trans_ret_rolename IN VARCHAR2,
i_activity_type IN VARCHAR2,
i_ret_list IN V_ARRAY,
result OUT VARCHAR2,
i_o_query OUT VARCHAR2
)
AS
--i_ret_codes OUT VARCHAR2;
v_dist_count NUMBER;
v_ret_count NUMBER;
v_ret_codes VARCHAR2(10000) := '';
v_flag VARCHAR2(10) := 'true';
v_trans_id NUMBER;
v_query VARCHAR2(10000);
BEGIN
IF i_territory_remapping = 1 then
SELECT count(*) into v_dist_count FROM tblemployee where EMPCODE = i_new_dist_code and circle_code = (select emp.circle_code
from tblemployee emp where emp.empcode = i_old_dist_code) and upper(user_type) like upper('%dist%') and upper(ACCESS_TO) in ('SALES','BOTH') and upper(stage) not in (upper('InActive'));
ELSE
SELECT count(*) into v_dist_count FROM tblemployee where EMPCODE = i_new_dist_code and circle_code = (select emp.circle_code from tblemployee emp
where emp.empcode = i_old_dist_code) and cluster_code = (select emp.cluster_code from tblemployee emp where emp.empcode = i_old_dist_code)
and upper(user_type) like upper('%dist%') and upper(ACCESS_TO) in ('SALES','BOTH') and upper(stage) not in (upper('InActive'));
END IF;
IF v_dist_count =0 THEN
result := 'invalid_new_dist_code';
v_flag := 'false';
ELSIF v_dist_count = 1 THEN
SELECT count(*) into v_ret_count FROM tblretailer t where t.DIST_CODE = i_old_dist_code and (upper(t.ACCESS_TO) = 'SALES' or upper(t.ACCESS_TO) = 'BOTH');
--SELECT count(*) into v_ret_count FROM tblretailer t where t.DIST_CODE = i_old_dist_code and upper(t.ACCESS_TO) = 'SALES' and upper(t.stage) in ('APPROVED','INACTIVE');
IF v_ret_count=i_ret_list.count THEN
IF i_territory_remapping = 1 THEN
result := 'no_ret_left';
v_flag := 'false';
END IF;
ELSE
IF i_territory_remapping != 1 THEN
result := 'ret_left';
v_flag := 'false';
END IF;
END IF;
END IF;
IF i_ret_list is null or i_ret_list.count = 0 THEN
result := 'empty retailers list';
v_flag := 'false';
END IF;
/*FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
IF v_ret_codes is null
THEN
v_ret_codes := ''''||i_ret_list(i)||'''';
ELSE
v_ret_codes := v_ret_codes||','''||i_ret_list(i)||'''';
END IF;
IF v_ret_codes is null
THEN
v_ret_codes := i_ret_list(i);
ELSE
v_ret_codes := v_ret_codes||','||i_ret_list(i);
END IF;
END LOOP;
i_ret_codes := v_ret_codes;
v_flag := 'false';
result := 'success';*/
IF v_flag = 'true' THEN
FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
IF v_ret_codes is null
THEN
v_ret_codes := ''''||i_ret_list(i)||'''';
ELSE
v_ret_codes := v_ret_codes||','''||i_ret_list(i)||'''';
END IF;
END LOOP;
--i_ret_codes := v_ret_codes;
--update tblretailer set dist_code=i_new_dist_code,DIST_ID=to_number(i_new_dist_code),cluster_code=(select cluster_code from tblemployee where empcode = i_new_dist_code),FOSID='',FOS_CODE='',DSR_ID='',DSR_CODE='',LAST_UPDATED_DATE=sysdate where retcode in (v_ret_codes);
v_query := 'update tblretailer set dist_code='||i_new_dist_code||',DIST_ID=to_number('||i_new_dist_code||'),cluster_code=(select cluster_code from tblemployee where empcode = '||i_new_dist_code||'),FOSID='''',FOS_CODE='''',DSR_ID='''',DSR_CODE='''',LAST_UPDATED_DATE=sysdate where retcode in ('||v_ret_codes||')';
execute immediate (v_query);
--i_query :='update tblretailer set dist_code='||i_new_dist_code||',DIST_ID=to_number('||i_new_dist_code||'),cluster_code=(select cluster_code from tblemployee where empcode = '||i_new_dist_code||'),FOSID='',FOS_CODE='',DSR_ID='',DSR_CODE='',LAST_UPDATED_DATE=sysdate where retcode in ('||v_ret_codes||');';
insert into TBL_TRANSFER_SUP_MASTER(MASTER_ID,TRANS_ID,TRANS_DONEBY_ROLENAME,TRANS_DONEBY_ID,TRANS_FROM_ROLENAME,TRANS_FROM,TRANS_TO_ROLENAME,TRANS_TO,ACTIVITY_CODE,TRANS_DATE,TRANSFER_REASON,LAST_UPDATED_DATE)
values(SUP_MASTER_TRANS_ID_SEQ.nextval,SUP_MASTER_TRANS_ID_SEQ.nextval,i_trans_doneby_rolename,i_trans_doneby_id,i_trans_dist_rolename,i_old_dist_code,i_trans_dist_rolename,i_new_dist_code,'101',sysdate,i_remapping_reason,sysdate) return TRANS_ID into v_trans_id;
FOR i IN i_ret_list.FIRST .. i_ret_list.LAST
LOOP
insert into TBL_TRANSFER_SUP_DTLS(DTLS_ID,TRANS_ID,TRANS_ON_ROLENAME,TRANS_ON_ID,LAST_UPDATED_DATE)
values(SUP_DTLS_ID_SEQ.nextval,v_trans_id,i_trans_ret_rolename,i_ret_list(i),sysdate);
END LOOP;
IF SQL%ROWCOUNT>0 THEN
result := 'success';
ELSE
result := 'failure';
END IF;
--update tblstock set NEW_DIST_CODE_REMAP=i_new_dist_code,REMAP_DATE=sysdate,LAST_UPDATED_DATE=sysdate where (DIST_CODE=i_old_dist_code or NEW_DIST_CODE_REMAP=i_old_dist_code) and RET_CODE in (v_ret_codes);
v_query := 'update tblstock set NEW_DIST_CODE_REMAP='||i_new_dist_code||',REMAP_DATE=sysdate,LAST_UPDATED_DATE=sysdate where (DIST_CODE='||i_old_dist_code||' or NEW_DIST_CODE_REMAP='||i_old_dist_code||') and RET_CODE in ('||v_ret_codes||')';
execute immediate (v_query);
i_o_query := v_query;
insert all into TBL_ACTIVITY_LOG (LOG_ID,TRANS_ID,ACTIVITY_DONEBY_ROLENAME,ACTIVITY_DONEBY_ID,ACTIVITY_REFERENCE_ID,ACTIVITY_CODE,ACTIVITY_DATE)
values(ACTIVITY_LOG_TRANS_ID_SEQ.NEXTVAL,ACTIVITY_LOG_TRANS_ID_SEQ.NEXTVAL,i_trans_doneby_rolename,i_trans_doneby_id,v_trans_id,
act_code,sysdate) select log_config.ACTIVITY_CODE act_code from TBL_ACTIVITY_LOG_CONFIG log_config
where upper(log_config.ACTIVITY_TYPE)= upper(i_activity_type);
END IF;
END;
/
Java Code :-
try{
if(ret_list.size()>0)
ret_code = ret_list.toArray();
con = ConnectionManager.getDirectConnection();
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(PropertyLoader.RET_SECONDARY_V_ARRAY,con);
ARRAY array_to_pass = new ARRAY( descriptor,con, ret_code );
cstmt = con.prepareCall("{ call SP_DIST_RETAILER_REMAP(?,?,?,?,?,?,?,?,?,?,?,?)}");
cstmt.setString(1,old_dist_code.trim());
cstmt.setString(2,new_dist_code.trim());
if(territory_remapping)
cstmt.setInt(3,1);
else
cstmt.setInt(3,2);
cstmt.setString(4,remapping_reason);
cstmt.setString(5,userVO.getRolename().trim());
cstmt.setInt(6,userVO.getEmpid());
cstmt.setString(7,PropertyLoader.DISTRIBUOTR_ROLENAME);
cstmt.setString(8,PropertyLoader.RETAILER_ROLENAME);
cstmt.setString(9,PropertyLoader.ACTIVITY_TYPES_RETAILER_REMAPPING);
cstmt.setArray(10,array_to_pass);
cstmt.registerOutParameter(11,Types.VARCHAR);
cstmt.registerOutParameter(12,Types.VARCHAR);
/*cstmt.registerOutParameter(13,Types.VARCHAR);*/
cstmt.execute();
status = cstmt.getString(11);
System.out.println("Remap Update Query "+cstmt.getString(12));
//System.out.println(cstmt.getString(13));
}
If the value stored in PropertyLoader.RET_SECONDARY_V_ARRAY is not "V_ARRAY", then you are using different types; even if they are declared identically (e.g. both are table of number) this will not work.
You're hitting this data type compatibility restriction:
You can assign a collection to a collection variable only if they have
the same data type. Having the same element type is not enough.
You're trying to call the procedure with a parameter that is a different type to the one it's expecting, which is what the error message is telling you.
The procedure which you are using is should be properly declared in the place which you are using it. For an example if it is under a user and in a package then it should be in that order. The username, package and procedurename.
I have the below procedure were the loop is breaking if the cursor does not have any record in it. I would like to contine the iteration even if the cursor does not have any record.
My procedure is,
CREATE OR REPLACE PROCEDURE "MAPSADMIN"."FORECAST_MAINTENANCE_SCH" (
in_carrierCode VARCHAR2,
in_WindowPeriodStr VARCHAR2,
out_forecastRecords OUT types.cursortype
)
IS
vtailAndCheckCur types.cursortype;
vForecastRecsCursor types.cursortype;
vtailNo VARCHAR2(10);
vmaintCheckType VARCHAR2(10);
vforcastRecords forecastObjectsList := forecastObjectsList();
forcastRec forecastObjectsList := forecastObjectsList();
BEGIN
dbms_output.enable(null);
OPEN vtailAndCheckCur FOR
select td.tail_number,mpm.maint_check_type
from tail_details td, maint_plan_tail_map mptm, maint_plan_master mpm
where td.tail_number = mptm.tail_number
and mpm.maint_plan_code = mptm.maint_plan_code
and mpm.carrier_code = in_carrierCode
UNION
select td.tail_number,mpm.maint_check_type
from tail_details td, maint_plan_subfleet_map mptm, maint_plan_master mpm
where td.subfleet_code = mptm.subfleet_code
and mpm.maint_plan_code = mptm.maint_plan_code
and mpm.carrier_code = in_carrierCode;
LOOP
FETCH vtailAndCheckCur INTO vtailNo, vmaintCheckType;
dbms_output.put_line( vtailNo||' '||vmaintCheckType );
FORECAST_OBJS_LIST(vtailNo,vmaintCheckType,in_WindowPeriodStr,vForecastRecsCursor);
LOOP
forcastRec.EXTEND;
forcastRec(forcastRec.COUNT) := FORECASTOBJECT(null,null,null,null,null,null,null,null,null,null);
dbms_output.put_line( 'test');
FETCH vForecastRecsCursor INTO
forcastRec(forcastRec.COUNT).maintNextPlanCode,
forcastRec(forcastRec.COUNT).tailNumber,
forcastRec(forcastRec.COUNT).maintNextCheckType,
forcastRec(forcastRec.COUNT).maintNextCycleCheckLabel,
forcastRec(forcastRec.COUNT).maintNextStartDate,
forcastRec(forcastRec.COUNT).maintNextEndDate,
forcastRec(forcastRec.COUNT).maintNextDueDate,
forcastRec(forcastRec.COUNT).maintNextCalendarDays,
forcastRec(forcastRec.COUNT).maintForecastFactor,
forcastRec(forcastRec.COUNT).maintCheckColor;
dbms_output.put_line( forcastRec(forcastRec.COUNT).maintNextPlanCode);
EXIT WHEN vForecastRecsCursor%NOTFOUND;
END LOOP;
EXIT WHEN vtailAndCheckCur%NOTFOUND;
END LOOP;
CLOSE vtailAndCheckCur;
OPEN out_forecastRecords FOR
SELECT tailNumber,maintNextCheckType,maintNextPlanCode,maintNextCycleCheckLabel,maintNextStartDate,
maintNextEndDate,maintNextDueDate,maintNextCalendarDays,maintForecastFactor,maintCheckColor
FROM TABLE(CAST(forcastRec AS forecastObjectsList));
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(DBMS_UTILITY.FORMAT_ERROR_STACK);
END FORECAST_MAINTENANCE_SCH;
/
Here if vForecastRecsCursor returns without 0 records in it i am getting ORA-01001: invalid cursor. Anyone please explain how to iterate further by ignoring the error.
Thanks in advance
Try to check if vForecastRecsCursor is opened:
IF vForecastRecsCursor%ISOPEN THEN
...
END IF;
You can control the loop by the GOTO clause or using blocks of code.
DECLARE
dummy_cur SYS_REFCURSOR;
l_dummy_num NUMBER;
CURSOR dual_cur IS
SELECT 1
FROM dual
WHERE 1 = 2;
l_dual_num NUMBER;
l_counter NUMBER := 0;
BEGIN
OPEN dummy_cur FOR SELECT 1 FROM dual;
LOOP
FETCH dummy_cur INTO l_dummy_num;
IF dummy_cur%NOTFOUND THEN
GOTO exit_command;
END IF;
-- inner cursor
BEGIN
-- open inner cursor
IF l_counter = 0 THEN
OPEN dual_cur;
END IF;
-- loop inner cursor
LOOP
FETCH dual_cur INTO l_dual_num;
DBMS_OUTPUT.PUT_LINE('inner loop');
EXIT WHEN dual_cur%NOTFOUND;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('exception');
END;
<<exit_command>>
EXIT WHEN dummy_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('l_dummy_num: ' || l_dummy_num);
l_counter := l_counter + 1;
DBMS_OUTPUT.PUT_LINE('l_counter: ' || l_counter);
END LOOP;
--close inner cursor
CLOSE dual_cur;
CLOSE dummy_cur;
EXCEPTION
WHEN OTHERS THEN
CLOSE dual_cur;
CLOSE dummy_cur;
END;