我在Oracle中编写了两个使用多个游标的数据库过程。面临的问题是,虽然98%的情况下执行过程没有任何错误,但在少数情况下,错误 - ORA-01001无效游标被抛出。
由于问题发生在运行时,因此很难确定原因。我无法复制过程引发错误的场景。
根据我的理解,由于98%的案例都没有任何问题地执行这两个程序,我认为原因不是由于Open-Fetch-Close命令无效。
知道抛出异常的可能原因是什么?
我正在添加示例代码:
CURSOR curWork(vCaseId VARCHAR2) IS
SELECT w.X_WORKFUNCTION_ID
FROM table_case c, table_queue w
WHERE c.id_number = vCaseId
AND c.CASE_CURRQ2QUEUE = w.objid;
CURSOR curPart(vCaseId VARCHAR2) IS
SELECT p.x_part_number, p.X_FAULT_CATEGORY, p.X_FORW_GRP_ID
FROM table_case c, table_mod_level m, table_x_part_forw_grp p, table_part_num n
WHERE c.id_number =vCaseId
AND c.CASE_PRT2PART_INFO =m.objid
And m.part_info2part_num=N.OBJID
AND N.S_PART_NUMBER=P.X_PART_NUMBER;
PROCEDURE UpdateAddressXY(vCaseId IN VARCHAR2, nStatus IN OUT NUMBER, vComment OUT VARCHAR2) IS
bContinue boolean;
nJobCode VARCHAR2(4);
cnt number;
CURSOR curAddress(vCaseId VARCHAR2) IS
select a.X_COORDINATE_X , a.X_COORDINATE_Y, A.X_XY_ORIGIN
from table_address a, table_case c
where C.ID_NUMBER =vCaseId
and a.objid =c.CASE2ADDRESS;
rAdd curAddress%ROWTYPE;
--Get Dok Details
CURSOR curDok(vCaseId VARCHAR2) IS
select dk.x_dok_card_type, dk.x_line_src from table_x_kat_dok dk, table_case c
where c.objid=DK.X_KAT_DOK2CASE
and c.id_number=vCaseId;
rDok curDok%ROWTYPE;
--Get Jobcode Details
CURSOR curJCode(vWorkFunction Number, nForwGrpId Number) IS
select x_code, x_code2, x_code3
from table_x_queue_jobcode
where X_WORKFUNCTION_ID=vWorkFunction
and X_FORW_GRP_ID=nForwGrpId;
rJCode curJCode%ROWTYPE;
rPart curPart%ROWTYPE;
rWork curWork%ROWTYPE;
BEGIN
bContinue := true;
-- get Part details
OPEN curPart(vCaseId);
FETCH curPart INTO rPart;
IF curPart%NOTFOUND THEN
CLOSE curPart;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Part Details Not Found | UpdateAddressXY';
END IF;
CLOSE curPart;
-- get Work details
OPEN curWork(vCaseId);
FETCH curWork INTO rWork;
IF curWork%NOTFOUND THEN
CLOSE curWork;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Work Details Not Found | UpdateAddressXY';
END IF;
CLOSE curWork;
-- get Addess details
OPEN curAddress(vCaseId);
FETCH curAddress INTO rAdd;
IF curAddress%NOTFOUND THEN
CLOSE curAddress;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Address Details Not Found | UpdateAddressXY';
END IF;
CLOSE curAddress;
--get Dok details
OPEN curDok(vCaseId);
FETCH curDok INTO rDok;
IF curDok%NOTFOUND THEN
CLOSE curDok;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Dok Details Not Found | UpdateAddressXY';
END IF;
CLOSE curDok;
--get Jobcode details
OPEN curJCode(rWork.X_WORKFUNCTION_ID,rPart.X_FORW_GRP_ID);
FETCH curJCode INTO rJCode;
IF curJCode%NOTFOUND THEN
CLOSE curJCode;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Jobcode Details Not Found | UpdateAddressXY';
END IF;
CLOSE curJCode;
if bContinue then
--job code
if ( Not (rDok.x_line_src is null OR rJCode.x_code3 is null OR upper(rDok.x_line_src)='DOK') ) then
nJobCode:= rJCode.x_code3;
elsif (rDok.x_dok_card_type is not null and rJCode.x_code2 is not null and ( substr(rDok.x_dok_card_type,1,1)='v' OR substr(rDok.x_dok_card_type,1,1)='V')) then
nJobCode:= rJCode.x_code2;
else
nJobCode:= rJCode.x_code;
End if;
select count(CASE_ID) into cnt from table_x_cu_address_jobcode where CASE_ID=vCaseId;
if cnt=0 then
Insert into table_x_cu_address_jobcode(CASE_ID, X_JOB_CODE, X_COORDINATE_X, X_COORDINATE_Y, X_XY_ORIGIN)
values(vCaseId,nJobCode,rAdd.X_COORDINATE_X,rAdd.X_COORDINATE_Y,rAdd.X_XY_ORIGIN);
else
Update table_x_cu_address_jobcode
set X_JOB_CODE=nJobCode,
X_COORDINATE_X=rAdd.X_COORDINATE_X,
X_COORDINATE_Y = rAdd.X_COORDINATE_Y,
X_XY_ORIGIN=rAdd.X_XY_ORIGIN
where CASE_ID=vCaseId;
end if;
END if;
EXCEPTION
WHEN OTHERS THEN
IF vErrorMsg IS NULL THEN
vErrorMsg := TO_CHAR(SQLCODE) || ' - ' || SQLERRM || cCRLF || ' | UpdateAddressXY';
ELSE
vErrorMsg := vErrorMsg || ' | UpdateAddressXY';
END IF;
nStatus := CONST.cError;
vComment := vErrorMsg;
insert into xxx(dat,seq,msg)
values(SYSDATE,71180,vComment ||'@' || DBMS_UTILITY.FORMAT_ERROR_STACK);
End;
答案 0 :(得分:3)
你试图关闭同一个光标两次 参见:
IF curPart%NOTFOUND THEN
CLOSE curPart;
bContinue := FALSE;
nStatus := CONST.cError;
vComment := 'Part Details Not Found | UpdateAddressXY';
END IF;
CLOSE curPart;
如果curPart%NOTFOUND
,则关闭curPart,之后(end if
之后)尝试再次关闭它。
如果您希望在curPart%NOTFOUND
然后使用if-else结构或raise_application_error时停止,如果不是 - 那么只需从{{1}中删除CLOSE curPart;
命令阻止