ORA-01001 无效游标错误

Posted

技术标签:

【中文标题】ORA-01001 无效游标错误【英文标题】:ORA-01001 Invalid cursor error 【发布时间】:2013-01-09 06:05:49 【问题描述】:

我在 Oracle 中编写了两个使用多个游标的数​​据库过程。面临的问题是,虽然在 98% 的情况下执行过程没有任何错误,但在少数情况下,会抛出错误 - ORA-01001 invalid cursor。

由于问题发生在运行时,因此很难确定原因。我无法复制过程引发错误的场景。

据我了解,由于 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;

【问题讨论】:

你能给我们看一些代码吗?难道你没有关闭游标,因为打开的游标比MAXOPENCURSORS 更多? @A.B.Cade - 我已经添加了代码。请检查 【参考方案1】:

您试图关闭同一个光标两次。 见:

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,如果不是,则只需从IF curPart%NOTFOUND ... END IF; 块中删除CLOSE curPart; 命令

【讨论】:

以上是关于ORA-01001 无效游标错误的主要内容,如果未能解决你的问题,请参考以下文章

循环退出条件中的“ORA-01001:无效游标”

PL/SQL:游标使用中的 ORA-01001

我在写游标时收到错误 ORA-01001 Invalid cursor show even number of records

奇怪的 PL SQL 无效游标

是啥导致了这个“无效的游标状态”错误?

关于resultset 的deleteRow方法报无效的游标位置的错误