【问题标题】:Skip invalid cursor and continue loop跳过无效光标并继续循环
【发布时间】:2013-08-16 01:45:33
【问题描述】:

如果光标中没有任何记录,我有以下过程是循环中断。即使光标没有任何记录,我也想继续迭代。

我的程序是,

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;

/

如果 vForecastRecsCursor 返回时没有 0 条记录,我将得到 ORA-01001: invalid cursor请任何人解释如何通过忽略错误来进一步迭代

提前致谢

【问题讨论】:

    标签: sql oracle plsql cursor


    【解决方案1】:

    尝试检查 vForecastRecsCursor 是否打开:

    IF vForecastRecsCursor%ISOPEN THEN
      ...
    END IF;
    

    【讨论】:

      【解决方案2】:

      您可以通过 GOTO 子句或使用代码块来控制循环。

      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;
      

      【讨论】:

      • 我不建议您在未检查 cursor%ISOPEN 的情况下关闭 WHERE OTHERS 部分中的游标。试想一下,在您打开其中一个游标之前或何时触发了错误!
      猜你喜欢
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2012-04-03
      • 2021-07-24
      相关资源
      最近更新 更多