Stored Procedure (rookie programmer), What's wrong with my code? - sql

I'm trying to create a stored procedure that will update a related row in the BugIt table given an expense report number ErepNo and expense category number EXNo.
The procedure must contain 3 input parameters EXNo ,ErepNo and the 'rUpAm' and with one boolean output parameter aRes.
If the ErepStatus is equal to 'Approved' then the stored value rUpAm is added to BIAct,the output parameter is set to TRUE and the row is updated.
Else the ErepStatus is equal to 'Denied' or 'Pending' an application error is raised and the output parameter is set to FALSE.
Here is what I have tried so far
CREATE OR REPLACE PROCEDURE StoredProcedure1
(tEXNo IN BugIt.EXNo%TYPE,
tErepNo IN ER.ErepNo%TYPE,
rUpAm IN INTEGER,
aRes OUT BOOLEAN ) IS
FOUND BOOLEAN := False;
tErepStatus ER.ErepStatus%TYPE;
tBIAct BugIt.BIAct%TYPE;
CURSOR ERCur(TmpErepNo ExpI.ErepNo%TYPE)is
SELECT ExpI.EXNo, ER.ErepStatus
FROM ER, BugIt, ExpI
WHERE ER.ErepNo = tErepNo
AND BugIt.EXNo = ExpI.EXNo
AND ER.ErepNo = ExpI.ErepNo
ORDER BY ErepStatus DESC;
BEGIN
OPEN ERCur(tErepNo);
LOOP
FETCH ERCur INTO tErepStatus, tBIAct;
EXIT WHEN ERCur%NOTFOUND;
IF tErepStatus = 'APPROVED' THEN
FOUND := TRUE;
END IF;
IF tErepStatus = 'PENDING' OR tErepStatus = 'DENIED' THEN
FOUND := False;
EXIT;
END IF;
END LOOP;
CLOSE ERCur;
IF FOUND THEN
tBIAct := tBIAct + rUpAm;
aRes := TRUE;
UPDATE BugIt
Set BIAct = tBIAct
WHere EXNo = tEXNo;
ElSE
tBIAct := tBIAct;
aRes := False;
END IF;
EXCEPTION
WHEN OTHERS THEN aRes := False;
raise_application_error(-20001, 'Database error');
END;
/
Here is my test case to implement the code that I have, which keeps coming up with errors(below)
---test--
SET Serveroutput on;
SELECT ExpI.EXNo, ER.ErepStatus
FROM ER, BugIt, ExpI
WHERE ER.ErepNo = 21
AND BugIt.EXNo = ExpI.EXNo
AND BugIt.ErepNo = ExpI.ErepNo
ORDER BY ErepStatus DESC;
-- Test script
DECLARE
Result BOOLEAN;
aBIAct BugIt.BIAct%TYPE;
BEGIN
StoredProcedure1(2, 2, 3, Result);
IF Result then
dbms_output.put_line('updated element to the BugIt table');
ELSE
dbms_output.put_line('Row not updated to the BugIt table');
END IF;
END;
/
ERROR at line 1:
ORA-20001: Database error
ORA-06512: at "SYSTEM.SPROLLUPEXPITEM", line 51
ORA-06512: at line 6

I think you want:
CREATE OR REPLACE PROCEDURE StoredProcedure1 (
tEXNo IN BugIt.EXNo%TYPE,
tErepNo IN ER.ErepNo%TYPE,
rUpAm IN INTEGER,
aRes OUT BOOLEAN
)
IS
tErepStatus ER.ErepStatus%TYPE;
BEGIN
SELECT ER.ErepStatus
INTO tErepStatus
FROM ER
INNER JOIN ExpI
ON ( ER.ErepNo = ExpI.ErepNo )
INNER JOIN BugIt
ON ( BugIt.EXNo = ExpI.EXNo )
WHERE ER.ErepNo = tErepNo
AND ER.ErepStatus IN ( 'APPROVED', 'PENDING', 'DENIED' )
ORDER BY ErepStatus DESC
FETCH FIRST ROW ONLY;
aRes := tErepStatus = 'APPROVED';
IF aRes THEN
UPDATE BugIt
SET BIAct = BIAct + rUpAm
WHERE EXNo = tEXNo;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
aRes := FALSE;
END;
/
Which, for the sample data:
CREATE TABLE ER ( ErepNo, Erepstatus ) AS
SELECT 1, 'APPROVED' FROM DUAL UNION ALL
SELECT 2, 'PENDING' FROM DUAL UNION ALL
SELECT 3, 'DENIED' FROM DUAL UNION ALL
SELECT 3, 'APPROVED' FROM DUAL;
CREATE TABLE ExpI ( ErepNo, EXNo ) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 2 FROM DUAL UNION ALL
SELECT 3, 3 FROM DUAL;
CREATE TABLE BugIt ( EXNo, BIAct ) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 2 FROM DUAL UNION ALL
SELECT 3, 3 FROM DUAL;
Then:
DECLARE
aRes BOOLEAN;
BEGIN
StoredProcedure1( 1, 1, 1, aRes );
IF ares THEN
DBMS_OUTPUT.PUT_LINE( 'Changed' );
ELSE
DBMS_OUTPUT.PUT_LINE( 'Not Changed' );
END IF;
END;
/
Outputs Changed and:
SELECT * FROM BugIt;
Gives:
EXNO | BIACT
---: | ----:
1 | 2
2 | 2
3 | 3
And:
DECLARE
aRes BOOLEAN;
BEGIN
StoredProcedure1( 3, 3, 1, aRes );
IF ares THEN
DBMS_OUTPUT.PUT_LINE( 'Changed' );
ELSE
DBMS_OUTPUT.PUT_LINE( 'Not Changed' );
END IF;
END;
/
Outputs Not Changed and the BugIt table has not changed.
db<>fiddle here

Related

E-mail Formatting Oracle

I need some help with this procedure. I need to include in a single e-mail the whole result of the select on the first Cursor (C1).
The way the procedure is working now, it sends an e-mail for each row found. The result is, if the cursor finds 100 rows, 100 e-mails will be sent, and I don't want that to happen, I need the 100 rows in a single e-mail, following the "V_MENSAGEM" structure.
create or replace PROCEDURE PR_ENVIA_EMAIL_LOTE_ESTOQUE IS
V_REMETENTE VARCHAR2(50) := 'servidor#oracle.com.br';
V_SAUDACAO VARCHAR2(50);
V_ASSUNTO VARCHAR2(200);
V_ASSINATURA VARCHAR2(100);
V_MENSAGEM VARCHAR2(6000);
V_COD_ERRO NUMBER(2);
V_MSG_ERRO VARCHAR2(1);
TDESCRI_ARMAZEM VARCHAR2(50);
TDESCRI VARCHAR2(60);
BEGIN
FOR C1 IN (SELECT TBLOTE.NNOTFIS NOTA_FISCAL,
TBLOTE.CLOTE LOTE,
TBARMAZ.TDESCRI ARMAZEM,
TBNOTF.DDTFATU DATA_FAT_NF,
TBLOTE.DRECEBTO DATA_RECEBTO,
TBLOTE.CPRODUT COD_PRODUTO,
TBPRODU.TDESCRI PRODUTO,
TBLOTAR.QQTESTQ QTD_ESTOQUE,
Decode(TBLOTE.F_ARMAZENAGEM, 'S', 'SIM', 'N', 'NÃO') ARMAZENAGEM,
Decode(TBLOTE.SLTENCR, 'S', 'SIM', 'N', 'NÃO') ENCERRADO,
TO_DATE(Sysdate, 'dd/mm/yyyy') - TO_DATE(TBLOTE.DRECEBTO, 'dd/mm/yyyy')DIAS_EM_ESTOQUE
FROM TBLOTE,
TBLOTAR,
TBPRODU,
TBARMAZ,
TBNOTF
WHERE TBLOTE.CPRODUT = TBPRODU.CPRODUT
AND TBLOTE.CLOTE = TBLOTAR.CLOTE
AND TBLOTAR.CARMAZE = TBARMAZ.CARMAZE
AND TBLOTE.NNOTFIS = TBNOTF.NNOTFIS
AND TBLOTE.CEMPRES = TBNOTF.CEMPRES
AND TBLOTE.SLTENCR = 'N'
AND TBLOTE.F_ARMAZENAGEM = 'S'
AND TBLOTE.NNOTFIS IS NOT NULL
AND TO_DATE(Sysdate, 'dd/mm/yyyy') - TO_DATE(TBLOTE.DRECEBTO, 'dd/mm/yyyy') >= 165
ORDER BY DIAS_EM_ESTOQUE DESC)
LOOP
DBMS_OUTPUT.PUT_LINE('LENDO '||C1.NOTA_FISCAL|| ' - ' ||C1.LOTE|| ' - ' ||C1.ARMAZEM|| ' - ' ||C1.PRODUTO|| ' - Dias em Estoque: ' || C1.DIAS_EM_ESTOQUE);
BEGIN
IF TO_NUMBER(TO_CHAR(SYSDATE,'HH24')) < 12 THEN
V_SAUDACAO:= 'Bom Dia!';
ELSIF TO_NUMBER(TO_CHAR(SYSDATE,'HH24')) >= 12 AND
TO_NUMBER(TO_CHAR(SYSDATE,'HH24')) < 18 THEN
V_SAUDACAO:= 'Boa tarde!';
ELSE
V_SAUDACAO:= 'Boa noite!';
END IF;
V_ASSUNTO := 'AVISO: Lotes em estoque.';
V_MENSAGEM := ' Os seguintes lotes ja estao há pelo menos 165 dias em nosso estoque, favor verificar: '||CHR(10)||CHR(10);
V_MENSAGEM := V_MENSAGEM ||'Nota Fiscal : '||C1.NOTA_FISCAL||CHR(10)||
'Lote : '||C1.LOTE||CHR(10)||
'Armazem : '||C1.ARMAZEM||CHR(10)||
'Dt. Faturamento : '||To_Date(C1.DATA_FAT_NF, 'DD/MM/YYYY')||CHR(10)||
'Dt. Recebimento : '||C1.DATA_RECEBTO||CHR(10)||
'Produto : '||C1.PRODUTO||CHR(10)||CHR(10)||
'Qtd. em Estoque : '||C1.QTD_ESTOQUE||CHR(10)||
'Dias em Estoque : '||C1.DIAS_EM_ESTOQUE||CHR(10)||CHR(10)||
'Estamos a disposiçao.'||CHR(10)||CHR(10)||CHR(10)||
'Att. '||CHR(10)||CHR(10)||
'Departamento de T.I'||CHR(10)||
'---';
V_MENSAGEM := V_SAUDACAO||CHR(10)||CHR(10)||
V_MENSAGEM||
CHR(10)||CHR(10)||CHR(10)||CHR(10)||
V_ASSINATURA;
FOR C2 IN (SELECT EMAIL_USUARIO
FROM TBEMAIL_INTERNO
WHERE F_LOTE_ESTOQUE = 'S'
AND F_EXCLUSAO_LOGICA = 'N')
LOOP
PR_ENVIA_EMAIL(V_REMETENTE,
C2.EMAIL_USUARIO,
V_ASSUNTO,
V_MENSAGEM,
V_COD_ERRO,
V_MSG_ERRO);
END LOOP;
END;
END LOOP ;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('ATENÇÃO: ERRO AO CHAMAR ROTINA PR_ENVIA_EMAIL_LOTE_ESTOQUE: '||SQLERRM);
END PR_ENVIA_EMAIL_LOTE_ESTOQUE;
The reason you're sending the email for every iteration of the loop through cursor C1 is that the loop through C2 (the one that sends the email) is inside the loop through C1. This change should fix your issue:
...
V_MENSAGEM := V_SAUDACAO||CHR(10)||CHR(10)||
V_MENSAGEM||
CHR(10)||CHR(10)||CHR(10)||CHR(10)||
V_ASSINATURA;
END;
END LOOP ;
FOR C2 IN (SELECT EMAIL_USUARIO
FROM TBEMAIL_INTERNO
WHERE F_LOTE_ESTOQUE = 'S'
AND F_EXCLUSAO_LOGICA = 'N')
LOOP
PR_ENVIA_EMAIL(V_REMETENTE,
C2.EMAIL_USUARIO,
V_ASSUNTO,
V_MENSAGEM,
V_COD_ERRO,
V_MSG_ERRO);
END LOOP;
EXCEPTION
...

Exception handling PL SQL

My Application has following two procedure which handles the entire transaction.
But when my nested procedure throws an exception the CRUD operation performed in outer procedure could not get roll back. Please help me to re arrange it or how could I write in better way so that I can roll back my transaction.
PROCEDURE SP_SEND_CASE_NEXT_LEVEL
(
p_wfId IN NUMBER,
p_assessmentId IN NUMBER,
p_prevLevelId IN NUMBER,
p_appType IN NUMBER,
p_sequenceNumber IN NUMBER,
p_subSequenceNumber IN NUMBER,
p_userCode IN VARCHAR2,
p_companyCode IN VARCHAR2,
p_camNumber IN VARCHAR2,
p_reviewType IN NUMBER,
p_unitType IN NUMBER,
p_regionCode IN NUMBER,
p_caseType IN VARCHAR2,
p_isApproved IN VARCHAR2,
p_fromUserCode IN VARCHAR2,
P_ERRORDETAIL OUT VARCHAR2
) IS
V_Newlevelid NUMBER(8);
V_NewWfId NUMBER(8);
v_StepCompleted NUMBER(2);
v_caseComplete VARCHAR2(1);
v_isStepComplete VARCHAR2(1);
v_isCompanyPicked VARCHAR2(1);
v_subUserInWorkflow NUMBER(1);
v_isPresent NUMBER(1);
v_inConsistentWorkFlow VARCHAR2(2);
v_subUserCode VARCHAR2(8);
v_errmsg VARCHAR2(50);
v_userDP NUMBER(10, 2);
v_sql VARCHAR2(2000);
v_sub_seq_no NUMBER(8);
v_reversalSequenceNo NUMBER(4);
v_reversalAppType NUMBER(2);
v_NewCourierId NUmber(8);
v_courierCount NUMBER(1);
v_revSequenceNo NUMBER(4);
v_courierComments VARCHAR2(4000);
v_required_count NUMBER(2);
v_sessionPriority NUMBER(1);
v_customRequiredCount NUMBER(1);
BEGIN
p_errorDetail := 'Failure';
v_inConsistentWorkFlow := 'N';
v_reversalAppType := 0;
v_revSequenceNo :=0;
v_courierComments := '';
v_customRequiredCount := 0;
SAVEPOINT Start_Tran;
BEGIN
-- update aph_comp_leveldetails for initiator of case
UPDATE Aph_Comp_Leveldetails
SET Case_Complete = 'Y',
End_Date = Sysdate,
Is_Step_Complete = 'Y',
is_approved = p_isApproved
WHERE User_Code = p_userCode
AND Assessmentid = p_assessmentId
and levelid = p_prevlevelid;
-- update Aph_Comp_Header for case status
UPDATE Aph_Comp_Header
SET CASE_STATUS_DESC = 'Pending',
COMP_REVERSE = 'N'
WHERE Assessmentid = p_assessmentId;
-- update MST_TAT_CALC set case end time for previous level user
UPDATE MST_TAT_CALC
SET CASE_END_TIME = sysdate,
RULE_END_TIME = sysdate,
days = fn_get_days(RULE_START_TIME, sysdate, REASON)
WHERE User_Code = p_userCode -- TODO : to be removed
and LEVELID = p_prevLevelId
AND ASSESSMENTID = p_assessmentId
and reason <> 'C' and CASE_END_TIME is null;
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
SELECT COUNT(CASE_COMPLETE) into v_required_count
FROM APH_COMP_LEVELDETAILS
WHERE ASSESSMENTID = p_assessmentid
AND SEQ_NO = p_sequenceNumber
AND APP_TYPE = p_appType
and COMP_REVERSE = 'N'
and COMP_WITHDRAWN = 'N'
and COMP_REJECTED = 'N';
SELECT COUNT(CASE_COMPLETE) into v_StepCompleted
FROM APH_COMP_LEVELDETAILS
WHERE ASSESSMENTID = p_assessmentid
AND SEQ_NO = p_sequenceNumber
AND APP_TYPE = p_appType
AND CASE_COMPLETE = 'Y'
and COMP_REVERSE = 'N'
and COMP_WITHDRAWN = 'N'
and COMP_REJECTED = 'N';
BEGIN
-- aph_comp_leveldetails
INSERT INTO aph_comp_leveldetails
(WF_ID,
ASSESSMENTID,
LEVELID,
User_Code,
Case_Complete,
COMP_FROMUSER,
SEQ_NO,
SUB_SEQ_NO,
COMP_TOUSER,
Start_Date,
IS_STEP_COMPLETE,
Is_Company_Picked,
App_Type,
WORK_FLOW_USER)
VALUES
(Send.Wf_Id,
p_assessmentId,
V_Newlevelid,
USER_ON_HOLIDAY.User_code,
'N',
--send.user_id,
P_USERCODE,
Send.Sequence_No,
v_sub_seq_no,
USER_ON_HOLIDAY.User_code,
Sysdate,
'N',
'N',
Send.App_Type,
Send.user_id);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into aph_comp_leveldetails as previous level step not completed';
RETURN;
END;
-------------------------------------------------------------------------------------------------
BEGIN
-- check if user is alreadily part of workflow.
SELECT COUNT(*)
INTO v_isPresent
FROM aph_wf_user
WHERE ASSESSMENTID = P_ASSESSMENTID
and USER_ID = USER_ON_HOLIDAY.USER_CODE
and is_wf_user = 'Y';
END;
-------------------------------------------------------------------------------------------------
IF v_isPresent = 0 THEN
-- if user is not alreadily part of workflow then insert into aph_wf_user.
BEGIN
-- insert in aph_wf_user
INSERT INTO aph_wf_user
(WF_ID,
ASSESSMENTID,
USER_ID,
SEQUENCE_NO,
APP_TYPE,
IS_EDITABLE,
USER_DP,
UNIT_TYPE,
CREATED_BY,
CREATION_DATE)
VALUES
(V_NewWfId,
P_ASSESSMENTID,
USER_ON_HOLIDAY.user_code,
Send.Sequence_No,
send.app_type,
'N',
v_userDP,
send.unit_type,
P_USERCODE,
sysdate);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into aph_comp_leveldetails as previous level step not completed';
RETURN;
END;
END IF; -- end of if v_isPresent = 0
-------------------------------------------------------------------------------------------------
BEGIN
--mst_tat_calc
INSERT INTO mst_tat_calc
(ASSESSMENTID,
LEVELID,
COMPANY_CODE,
USER_CODE,
REASON,
CASE_START_TIME,
CASE_END_TIME,
RULE_START_TIME,
RULE_END_TIME,
CAM_NUMBER,
REVIEW_TYPE,
UNIT_TYPE,
REGION_CODE,
LEVELID_COURIER_TO)
VALUES
(P_ASSESSMENTID,
/*p_prevLevelId,*/
V_NEWLEVELID,
P_COMPANYCODE,
/*p_userCode,*/
USER_ON_HOLIDAY.user_code,
'C',--This should be value of enum CommonActionEnum.COURIER
sysdate,
null,
sysdate,
null,
p_camNumber,
p_reviewType,
p_unitType,
P_REGIONCODE,
/*V_Newlevelid*/
p_prevLevelId
);
-------------------------------------------------------------------------------------------------
INSERT INTO mst_tat_calc
(ASSESSMENTID,
LEVELID,
COMPANY_CODE,
USER_CODE,
REASON,
CASE_START_TIME,
RULE_START_TIME,
CAM_NUMBER,
REVIEW_TYPE,
UNIT_TYPE,
REGION_CODE,
DAYS)
VALUES
(P_ASSESSMENTID,
V_NEWLEVELID,
p_companyCode,
USER_ON_HOLIDAY.user_code,
'N',--This should be value of enum CommonActionEnum.NORMAL_APPROVAL
sysdate,
fn_get_rule_date(sysdate),
p_camNumber,
p_reviewType,
p_unitType,
p_regionCode,
0);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into mst_tat_calc as normal approver';
RETURN;
END;
-------------------------------------------------------------------------------------------------
-- Check for if user has any courier
BEGIN
-- update in aph_user_Courier as courier status sent and sent date
SELECT COUNT(1)
INTO v_courierCount
FROM aph_user_courier
WHERE assessmentid = p_assessmentid
AND touser = USER_ON_HOLIDAY.User_code
AND levelid = p_prevlevelid;
if v_courierCount = 0 then
begin
Pack_Aph_Getid.Proc_Aph_Getid('APH_USER_COURIER','COURIER_ID', v_NewCourierId); -- generate courier id.
end;
INSERT
INTO APH_USER_COURIER
(
COURIER_ID,
ASSESSMENTID,
LEVELID,
FROMUSER,
TOUSER,
FROMUSER_COMMENTS,
TOUSER_COMMENTS,
FROMCOURIER_STATUS,
TOCOURIER_STATUS,
FROM_DATETIME,
TO_DATETIME,
DOCUMENTRECEIVED,
RECEIVEDDATE
)
--values (v_NewCourierId, p_assessmentid, V_Newlevelid, p_usercode, Send.User_Id, null, null, 'SENT' , null , sysdate , null, null, null);
VALUES
(
v_NewCourierId,
p_assessmentid,
V_Newlevelid,
p_usercode,
USER_ON_HOLIDAY.User_code,
v_courierComments,
NULL,
'SENT' ,
NULL ,
sysdate ,
NULL,
NULL,
NULL
);
else
UPDATE aph_user_Courier
SET fromcourier_status = 'SENT',
tocourier_status = null,
FROM_DATETIME = SYSDATE
WHERE assessmentid = p_assessmentid
AND levelid = p_prevlevelid
--AND touser = Send.User_Id;
AND touser = USER_ON_HOLIDAY.User_code
end if;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to update aph_user_Courier';
RETURN;
END;
BEGIN
SP_COMMON_INSERTS(p_assessmentId, p_prevLevelId, V_Newlevelid, 'N', 'N',0,'0','N', p_errorDetail)
EXCEPTION
WHEN OTHERS THEN
p_Errordetail := 'Error in common';
ROLLBACK;
END;
BEGIN
UPDATE APH_WF_USER set IS_EDITABLE = 'N' where USER_ID = Send.User_Id and ASSESSMENTID = p_assessmentId;
END;
END;
END SP_SEND_CASE_NEXT_LEVEL;
Procedure Sp_Common_Inserts
(
--p_wfId In Number,
p_assessmentId In Number,
p_prevLevelId In Number,
p_Newlevelid in number,
p_withdraw in varchar2,
p_rejected in varchar2,
p_prevAssessmentId in Number,
p_borrowerCode in varchar2,
p_srm_lcr in varchar2,
p_errorDetail Out Varchar2
) Is
v_wfId Number(8);
V_Errmsg Varchar2(50);
v_initiatorUserCode varchar2(50);
V_SrNo Number(8);
Begin
-- Savepoint Start_Tran1;
if p_withdraw = 'N' and p_rejected = 'N' then
begin
-- APH_ASSESSMENT_PARAMETER
INSERT INTO APH_ASSESSMENT_PARAMETER
(
SR_NO,
ASSESSMENTID,
LEVELID,
CAM_DATE,
REVISION_DATE,
SRM_EXPIRY_DATE,
PART_PROGRAM,
PRODUCT_PROGRAM,
PRODUCT_PROGRM_EXPOSURE,
PROGRM_PARAMETERS_ADHERED,
IS_SEPARETE_APPROVER,
CASH_BACKED_EXPOSURE,
EXPOSURE_GURANTED,
CLIMS_ID,
CAM_LOGIN_DATE,
BORROWER_RATING,
RATING_TYPE,
RATING_FINALISATION_DATE,
INITIAL_LABELLING_DATE,
CURRENT_REVIEW_DATE,
LABEL_REVIEW_TYPE,
LABEL,
LAST_CLIENT_CALL_DATE,
CALLED_ON_DATE,
INTERFACE_DATE,
COMP_CODE
) SELECT
SR_NO,
p_assessmentId,
p_Newlevelid,
CAM_DATE,
REVISION_DATE,
SRM_EXPIRY_DATE,
PART_PROGRAM,
PRODUCT_PROGRAM,
PRODUCT_PROGRM_EXPOSURE,
PROGRM_PARAMETERS_ADHERED,
IS_SEPARETE_APPROVER,
CASH_BACKED_EXPOSURE,
EXPOSURE_GURANTED,
CLIMS_ID,
CAM_LOGIN_DATE,
BORROWER_RATING,
RATING_TYPE,
RATING_FINALISATION_DATE,
INITIAL_LABELLING_DATE,
CURRENT_REVIEW_DATE,
LABEL_REVIEW_TYPE,
LABEL,
LAST_CLIENT_CALL_DATE,
CALLED_ON_DATE,
INTERFACE_DATE,
COMP_CODE
From APH_ASSESSMENT_PARAMETER
Where Levelid = p_prevlevelid;
Exception
When No_Data_Found Then
rollback;
v_errmsg := 'Unable to insert into APH_ADDENDUM_DETAILS as no data found at previous level';
return;
end;
end if;
IF P_WITHDRAW = 'Y' or P_REJECTED = 'Y' THEN
--APH_APPRAISAL_DETAILS
begin
INSERT INTO APH_APPRAISAL_DETAILS
(
ASSESSMENTID,
COMPANY_CODE,
CAM_FORMAT_ID,
FILE_NAME,
ORDER_ID,
REPORTS_HTML_CONTENTS,
SR_NO
)SELECT
p_assessmentId,
COMPANY_CODE,
CAM_FORMAT_ID,
FILE_NAME,
ORDER_ID,
REPORTS_HTML_CONTENTS,
SR_NO
FROM APH_APPRAISAL_DETAILS
WHERE ASSESSMENTID = P_prevAssessmentId
AND FILE_NAME NOT IN (SELECT FILE_NAME FROM APH_FTL_DETAILS WHERE FTL_ID IN(29,30,31));
Exception
When No_Data_Found Then
rollback;
v_errmsg := 'Unable to insert into APH_BORROWER_DETAILS as no data found at previous level';
Return;
End;
END IF;
p_Errordetail:='SUCCESS';
Exception
When Others Then
Rollback;
p_Errordetail :=v_errmsg;
End Sp_Common_Inserts;
Please let me know how to handle exception in above two procedures if nested procedure sp_common_insert throws an exception.
Instead of using RETURN, use RAISE instead. That way, the error encountered in your sub blocks will also trigger the exception that sets the value of p_Errordetail in your main block. Another thing is that you don't have an EXCEPTION block in SP_SEND_CASE_NEXT_LEVEL procedure's main block. Here's a revision of your code:
PROCEDURE SP_SEND_CASE_NEXT_LEVEL
(
p_wfId IN NUMBER,
p_assessmentId IN NUMBER,
p_prevLevelId IN NUMBER,
p_appType IN NUMBER,
p_sequenceNumber IN NUMBER,
p_subSequenceNumber IN NUMBER,
p_userCode IN VARCHAR2,
p_companyCode IN VARCHAR2,
p_camNumber IN VARCHAR2,
p_reviewType IN NUMBER,
p_unitType IN NUMBER,
p_regionCode IN NUMBER,
p_caseType IN VARCHAR2,
p_isApproved IN VARCHAR2,
p_fromUserCode IN VARCHAR2,
P_ERRORDETAIL OUT VARCHAR2
) IS
V_Newlevelid NUMBER(8);
V_NewWfId NUMBER(8);
v_StepCompleted NUMBER(2);
v_caseComplete VARCHAR2(1);
v_isStepComplete VARCHAR2(1);
v_isCompanyPicked VARCHAR2(1);
v_subUserInWorkflow NUMBER(1);
v_isPresent NUMBER(1);
v_inConsistentWorkFlow VARCHAR2(2);
v_subUserCode VARCHAR2(8);
v_errmsg VARCHAR2(50);
v_userDP NUMBER(10, 2);
v_sql VARCHAR2(2000);
v_sub_seq_no NUMBER(8);
v_reversalSequenceNo NUMBER(4);
v_reversalAppType NUMBER(2);
v_NewCourierId NUmber(8);
v_courierCount NUMBER(1);
v_revSequenceNo NUMBER(4);
v_courierComments VARCHAR2(4000);
v_required_count NUMBER(2);
v_sessionPriority NUMBER(1);
v_customRequiredCount NUMBER(1);
BEGIN
p_errorDetail := 'Failure';
v_inConsistentWorkFlow := 'N';
v_reversalAppType := 0;
v_revSequenceNo :=0;
v_courierComments := '';
v_customRequiredCount := 0;
SAVEPOINT Start_Tran;
BEGIN
-- update aph_comp_leveldetails for initiator of case
UPDATE Aph_Comp_Leveldetails
SET Case_Complete = 'Y',
End_Date = Sysdate,
Is_Step_Complete = 'Y',
is_approved = p_isApproved
WHERE User_Code = p_userCode
AND Assessmentid = p_assessmentId
and levelid = p_prevlevelid;
-- update Aph_Comp_Header for case status
UPDATE Aph_Comp_Header
SET CASE_STATUS_DESC = 'Pending',
COMP_REVERSE = 'N'
WHERE Assessmentid = p_assessmentId;
-- update MST_TAT_CALC set case end time for previous level user
UPDATE MST_TAT_CALC
SET CASE_END_TIME = sysdate,
RULE_END_TIME = sysdate,
days = fn_get_days(RULE_START_TIME, sysdate, REASON)
WHERE User_Code = p_userCode -- TODO : to be removed
and LEVELID = p_prevLevelId
AND ASSESSMENTID = p_assessmentId
and reason <> 'C' and CASE_END_TIME is null;
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
SELECT COUNT(CASE_COMPLETE) into v_required_count
FROM APH_COMP_LEVELDETAILS
WHERE ASSESSMENTID = p_assessmentid
AND SEQ_NO = p_sequenceNumber
AND APP_TYPE = p_appType
and COMP_REVERSE = 'N'
and COMP_WITHDRAWN = 'N'
and COMP_REJECTED = 'N';
SELECT COUNT(CASE_COMPLETE) into v_StepCompleted
FROM APH_COMP_LEVELDETAILS
WHERE ASSESSMENTID = p_assessmentid
AND SEQ_NO = p_sequenceNumber
AND APP_TYPE = p_appType
AND CASE_COMPLETE = 'Y'
and COMP_REVERSE = 'N'
and COMP_WITHDRAWN = 'N'
and COMP_REJECTED = 'N';
BEGIN
-- aph_comp_leveldetails
INSERT INTO aph_comp_leveldetails
(WF_ID,
ASSESSMENTID,
LEVELID,
User_Code,
Case_Complete,
COMP_FROMUSER,
SEQ_NO,
SUB_SEQ_NO,
COMP_TOUSER,
Start_Date,
IS_STEP_COMPLETE,
Is_Company_Picked,
App_Type,
WORK_FLOW_USER)
VALUES
(Send.Wf_Id,
p_assessmentId,
V_Newlevelid,
USER_ON_HOLIDAY.User_code,
'N',
--send.user_id,
P_USERCODE,
Send.Sequence_No,
v_sub_seq_no,
USER_ON_HOLIDAY.User_code,
Sysdate,
'N',
'N',
Send.App_Type,
Send.user_id);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into aph_comp_leveldetails as previous level step not completed';
RAISE;
END;
-------------------------------------------------------------------------------------------------
BEGIN
-- check if user is alreadily part of workflow.
SELECT COUNT(*)
INTO v_isPresent
FROM aph_wf_user
WHERE ASSESSMENTID = P_ASSESSMENTID
and USER_ID = USER_ON_HOLIDAY.USER_CODE
and is_wf_user = 'Y';
END;
-------------------------------------------------------------------------------------------------
IF v_isPresent = 0 THEN
-- if user is not alreadily part of workflow then insert into aph_wf_user.
BEGIN
-- insert in aph_wf_user
INSERT INTO aph_wf_user
(WF_ID,
ASSESSMENTID,
USER_ID,
SEQUENCE_NO,
APP_TYPE,
IS_EDITABLE,
USER_DP,
UNIT_TYPE,
CREATED_BY,
CREATION_DATE)
VALUES
(V_NewWfId,
P_ASSESSMENTID,
USER_ON_HOLIDAY.user_code,
Send.Sequence_No,
send.app_type,
'N',
v_userDP,
send.unit_type,
P_USERCODE,
sysdate);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into aph_comp_leveldetails as previous level step not completed';
RAISE;
END;
END IF; -- end of if v_isPresent = 0
-------------------------------------------------------------------------------------------------
BEGIN
--mst_tat_calc
INSERT INTO mst_tat_calc
(ASSESSMENTID,
LEVELID,
COMPANY_CODE,
USER_CODE,
REASON,
CASE_START_TIME,
CASE_END_TIME,
RULE_START_TIME,
RULE_END_TIME,
CAM_NUMBER,
REVIEW_TYPE,
UNIT_TYPE,
REGION_CODE,
LEVELID_COURIER_TO)
VALUES
(P_ASSESSMENTID,
/*p_prevLevelId,*/
V_NEWLEVELID,
P_COMPANYCODE,
/*p_userCode,*/
USER_ON_HOLIDAY.user_code,
'C',--This should be value of enum CommonActionEnum.COURIER
sysdate,
null,
sysdate,
null,
p_camNumber,
p_reviewType,
p_unitType,
P_REGIONCODE,
/*V_Newlevelid*/
p_prevLevelId
);
-------------------------------------------------------------------------------------------------
INSERT INTO mst_tat_calc
(ASSESSMENTID,
LEVELID,
COMPANY_CODE,
USER_CODE,
REASON,
CASE_START_TIME,
RULE_START_TIME,
CAM_NUMBER,
REVIEW_TYPE,
UNIT_TYPE,
REGION_CODE,
DAYS)
VALUES
(P_ASSESSMENTID,
V_NEWLEVELID,
p_companyCode,
USER_ON_HOLIDAY.user_code,
'N',--This should be value of enum CommonActionEnum.NORMAL_APPROVAL
sysdate,
fn_get_rule_date(sysdate),
p_camNumber,
p_reviewType,
p_unitType,
p_regionCode,
0);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to insert into mst_tat_calc as normal approver';
RAISE;
END;
-------------------------------------------------------------------------------------------------
-- Check for if user has any courier
BEGIN
-- update in aph_user_Courier as courier status sent and sent date
SELECT COUNT(1)
INTO v_courierCount
FROM aph_user_courier
WHERE assessmentid = p_assessmentid
AND touser = USER_ON_HOLIDAY.User_code
AND levelid = p_prevlevelid;
if v_courierCount = 0 then
begin
Pack_Aph_Getid.Proc_Aph_Getid('APH_USER_COURIER','COURIER_ID', v_NewCourierId); -- generate courier id.
end;
INSERT
INTO APH_USER_COURIER
(
COURIER_ID,
ASSESSMENTID,
LEVELID,
FROMUSER,
TOUSER,
FROMUSER_COMMENTS,
TOUSER_COMMENTS,
FROMCOURIER_STATUS,
TOCOURIER_STATUS,
FROM_DATETIME,
TO_DATETIME,
DOCUMENTRECEIVED,
RECEIVEDDATE
)
--values (v_NewCourierId, p_assessmentid, V_Newlevelid, p_usercode, Send.User_Id, null, null, 'SENT' , null , sysdate , null, null, null);
VALUES
(
v_NewCourierId,
p_assessmentid,
V_Newlevelid,
p_usercode,
USER_ON_HOLIDAY.User_code,
v_courierComments,
NULL,
'SENT' ,
NULL ,
sysdate ,
NULL,
NULL,
NULL
);
else
UPDATE aph_user_Courier
SET fromcourier_status = 'SENT',
tocourier_status = null,
FROM_DATETIME = SYSDATE
WHERE assessmentid = p_assessmentid
AND levelid = p_prevlevelid
--AND touser = Send.User_Id;
AND touser = USER_ON_HOLIDAY.User_code
end if;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_errmsg := 'Unable to update aph_user_Courier';
RAISE;
END;
BEGIN
SP_COMMON_INSERTS(p_assessmentId, p_prevLevelId, V_Newlevelid, 'N', 'N',0,'0','N', p_errorDetail)
EXCEPTION
WHEN OTHERS THEN
p_Errordetail := 'Error in common';
ROLLBACK;
END;
BEGIN
UPDATE APH_WF_USER set IS_EDITABLE = 'N' where USER_ID = Send.User_Id and ASSESSMENTID = p_assessmentId;
END;
END;
Exception
When Others Then
Rollback;
p_Errordetail :=v_errmsg;
END SP_SEND_CASE_NEXT_LEVEL;
Procedure Sp_Common_Inserts
(
--p_wfId In Number,
p_assessmentId In Number,
p_prevLevelId In Number,
p_Newlevelid in number,
p_withdraw in varchar2,
p_rejected in varchar2,
p_prevAssessmentId in Number,
p_borrowerCode in varchar2,
p_srm_lcr in varchar2,
p_errorDetail Out Varchar2
) Is
v_wfId Number(8);
V_Errmsg Varchar2(50);
v_initiatorUserCode varchar2(50);
V_SrNo Number(8);
Begin
-- Savepoint Start_Tran1;
if p_withdraw = 'N' and p_rejected = 'N' then
begin
-- APH_ASSESSMENT_PARAMETER
INSERT INTO APH_ASSESSMENT_PARAMETER
(
SR_NO,
ASSESSMENTID,
LEVELID,
CAM_DATE,
REVISION_DATE,
SRM_EXPIRY_DATE,
PART_PROGRAM,
PRODUCT_PROGRAM,
PRODUCT_PROGRM_EXPOSURE,
PROGRM_PARAMETERS_ADHERED,
IS_SEPARETE_APPROVER,
CASH_BACKED_EXPOSURE,
EXPOSURE_GURANTED,
CLIMS_ID,
CAM_LOGIN_DATE,
BORROWER_RATING,
RATING_TYPE,
RATING_FINALISATION_DATE,
INITIAL_LABELLING_DATE,
CURRENT_REVIEW_DATE,
LABEL_REVIEW_TYPE,
LABEL,
LAST_CLIENT_CALL_DATE,
CALLED_ON_DATE,
INTERFACE_DATE,
COMP_CODE
) SELECT
SR_NO,
p_assessmentId,
p_Newlevelid,
CAM_DATE,
REVISION_DATE,
SRM_EXPIRY_DATE,
PART_PROGRAM,
PRODUCT_PROGRAM,
PRODUCT_PROGRM_EXPOSURE,
PROGRM_PARAMETERS_ADHERED,
IS_SEPARETE_APPROVER,
CASH_BACKED_EXPOSURE,
EXPOSURE_GURANTED,
CLIMS_ID,
CAM_LOGIN_DATE,
BORROWER_RATING,
RATING_TYPE,
RATING_FINALISATION_DATE,
INITIAL_LABELLING_DATE,
CURRENT_REVIEW_DATE,
LABEL_REVIEW_TYPE,
LABEL,
LAST_CLIENT_CALL_DATE,
CALLED_ON_DATE,
INTERFACE_DATE,
COMP_CODE
From APH_ASSESSMENT_PARAMETER
Where Levelid = p_prevlevelid;
Exception
When No_Data_Found Then
rollback;
v_errmsg := 'Unable to insert into APH_ADDENDUM_DETAILS as no data found at previous level';
RAISE;
end;
end if;
IF P_WITHDRAW = 'Y' or P_REJECTED = 'Y' THEN
--APH_APPRAISAL_DETAILS
begin
INSERT INTO APH_APPRAISAL_DETAILS
(
ASSESSMENTID,
COMPANY_CODE,
CAM_FORMAT_ID,
FILE_NAME,
ORDER_ID,
REPORTS_HTML_CONTENTS,
SR_NO
)SELECT
p_assessmentId,
COMPANY_CODE,
CAM_FORMAT_ID,
FILE_NAME,
ORDER_ID,
REPORTS_HTML_CONTENTS,
SR_NO
FROM APH_APPRAISAL_DETAILS
WHERE ASSESSMENTID = P_prevAssessmentId
AND FILE_NAME NOT IN (SELECT FILE_NAME FROM APH_FTL_DETAILS WHERE FTL_ID IN(29,30,31));
Exception
When No_Data_Found Then
rollback;
v_errmsg := 'Unable to insert into APH_BORROWER_DETAILS as no data found at previous level';
RAISE;
End;
END IF;
p_Errordetail:='SUCCESS';
Exception
When Others Then
Rollback;
p_Errordetail :=v_errmsg;
End Sp_Common_Inserts;

use a validation function for an element in apex 5.0

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;

Procedure takes several hours to complete

I'm trying to generate a report that give me the percentage of each grade for each letter for each term for each subject. The final report has subject codes like MAT, ENC, etc. as the row headers and then the terms and letter grades as the column headers. I'm currently looping through each subject, then each term, then each grade and it takes 2+ hours to complete. What is the correct/more efficient way of accomplishing this. Feel free to ask if you have any questions. Thanks for your help!!
v_subj varchar2(5);
v_grade varchar2(5);
v_termloop varchar2(6);
c_total number;
c_dfw number;
c_gradetotal number;
c_gradedfw number;
v_output varchar2(1000);
Cursor Get_Terms is
select distinct ssbsect_term_code from ssbsect
where ssbsect_term_code >= 201230
and ssbsect_term_code not like '%5'
order by 1;
Cursor Get_Subj is
Select distinct ssbsect_subj_code from ssbsect
where ssbsect_term_code >= 201230
and ssbsect_insm_code = 'DL'
and ssbsect_term_code not like '%5'
order by 1;
Cursor Get_Grade is
select distinct msvcrse_grde_code from msvcrse
where msvcrse_grde_code in ('A','B','C','D','F','S','U','W')
order by 1;
Cursor Get_Total is
select count(msvcrse_pidm) from msvcrse
join ssbsect on msvcrse_crn = ssbsect_crn
and msvcrse_Term_code = ssbsect_term_code
where msvcrse_term_code = v_termloop
and ssbsect_insm_code = 'DL'
and msvcrse_crse_numb < '3000'
and msvcrse_subj_code = v_subj
and msvcrse_gmod_code <> 'D';
Cursor Get_GradeTotal is
select count(msvcrse_pidm) from msvcrse
join ssbsect on msvcrse_crn = ssbsect_crn
and msvcrse_Term_code = ssbsect_term_code
where msvcrse_term_code = v_termloop
and ssbsect_insm_code = 'DL'
and msvcrse_grde_code like '%'||v_grade||'%'
and msvcrse_crse_numb < '3000'
and msvcrse_subj_code = v_subj
and msvcrse_gmod_code <> 'D';
Begin
Open Get_Subj;
Loop
Fetch Get_Subj into v_subj;
Exit when Get_Subj%NOTFOUND;
v_output := '';
v_output := v_subj;
Open Get_Terms;
Loop
Fetch Get_Terms into v_termloop;
Exit when Get_Terms%NOTFOUND;
Open Get_Grade;
Loop
Fetch Get_Grade into v_grade;
Exit when Get_grade%NOTFOUND;
Open Get_Total;
Fetch Get_Total into c_total;
Close Get_Total;
Open Get_GradeTotal;
Fetch Get_GradeTotal into c_gradetotal;
Close Get_GradeTotal;
if c_total = 0 then
c_total := NULL;
end if;
v_output := v_output ||'|'||nvl(100*(round(c_gradetotal/c_total,3)),0);
--dbms_output.put_line(v_subj||'|'||v_termloop||'|'||v_insm||'|'||nvl(100*(round(c_dfw/c_total,3)),0));
End Loop;
Close Get_Grade;
End Loop;
Close Get_Terms;
dbms_output.put_line(v_output);
I change a little bit your code, but the result should be the same.
Please merge the cursors get_grade and get_gradetotal, makes no sense have two in this code.
DECLARE
c_total NUMBER;
v_output VARCHAR2 ( 1000 );
CURSOR get_subj IS
SELECT DISTINCT ssbsect_subj_code
FROM ssbsect
WHERE ssbsect_term_code >= 201230
AND ssbsect_insm_code = 'DL'
AND ssbsect_term_code NOT LIKE '%5'
ORDER BY 1;
CURSOR get_terms IS
SELECT DISTINCT ssbsect_term_code
FROM ssbsect
WHERE ssbsect_term_code >= 201230
AND ssbsect_term_code NOT LIKE '%5'
ORDER BY 1;
CURSOR get_total ( lci_termloop IN ssbsect.msvcrse_term_code%TYPE
, lci_subj IN msvcrse.msvcrse_subj_code%TYPE ) IS
SELECT COUNT ( msvcrse_pidm )
FROM msvcrse
JOIN ssbsect
ON msvcrse_crn = ssbsect_crn
AND msvcrse_term_code = ssbsect_term_code
WHERE msvcrse_term_code = lci_termloop
AND ssbsect_insm_code = 'DL'
AND msvcrse_crse_numb < '3000'
AND msvcrse_subj_code = lci_subj
AND msvcrse_gmod_code <> 'D';
CURSOR get_grade IS
SELECT DISTINCT msvcrse_grde_code
FROM msvcrse
WHERE msvcrse_grde_code IN ('A', 'B', 'C', 'D', 'F', 'S', 'U', 'W')
ORDER BY 1;
CURSOR get_gradetotal ( lci_termloop IN ssbsect.msvcrse_term_code%TYPE
, lci_grade IN msvcrse.msvcrse_grde_code%TYPE
, lci_subj IN msvcrse.msvcrse_subj_code%TYPE ) IS
SELECT COUNT ( msvcrse_pidm ) AS msvcrse_pidm
FROM msvcrse
JOIN ssbsect
ON msvcrse_crn = ssbsect_crn
AND msvcrse_term_code = ssbsect_term_code
WHERE msvcrse_term_code = lci_termloop
AND ssbsect_insm_code = 'DL'
AND msvcrse_grde_code LIKE '%' || lci_grade || '%'
AND msvcrse_crse_numb < '3000'
AND msvcrse_subj_code = lci_subj
AND msvcrse_gmod_code <> 'D';
BEGIN
FOR rec_subj IN get_subj LOOP
v_output := rec_subj.ssbsect_subj_code;
FOR rec_term IN get_terms LOOP
OPEN get_total ( lci_termloop => rec_term.ssbsect_term_code
, lci_subj => rec_subj.ssbsect_subj_code );
FETCH get_total INTO c_total;
CLOSE get_total;
FOR rec_grade IN get_grade LOOP
<<grade_total>>
FOR rec_gradetotal IN get_gradetotal ( lci_termloop => rec_term.ssbsect_term_code
, lci_grade => rec_grade.msvcrse_grde_code
, lci_subj => v_output ) LOOP
IF c_total = 0 THEN
c_total := NULL;
v_output := v_output || '|';
CONTINUE grade_total; -- <-- AVOID WORK
END IF;
v_output := v_output || '|' || NVL ( 100 * ( ROUND ( rec_gradetotal.msvcrse_pidm / c_total, 3 ) ), 0 ); -- <-- PLEASE MAKE THIS CODE BETTER
--dbms_output.put_line(rec_subj.ssbsect_subj_code||'|'||rec_term.ssbsect_term_code||'|'||v_insm||'|'||nvl(100*(round(c_dfw/c_total,3)),0));
END LOOP grade_total;
END LOOP;
END LOOP;
--DBMS_OUTPUT.put_line ( rec_subj.ssbsect_subj_code );
END LOOP;
END;
I change all code without compile, please make sure the types used int the cursor.
I guess 50% of improvement, but you need test.
Let me know whether you have any question and please use table alias in SQL and be careful with loops.
Thank you.

ORA-06550: line 1, column 7 (PL/SQL: Statement ignored) 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.