跳过无效游标并继续循环

时间:2013-08-14 07:55:40

标签: sql oracle plsql cursor

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

我的程序是,

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:游标无效任何人都可以通过忽略错误来解释如何进一步迭代

提前致谢

2 个答案:

答案 0 :(得分:0)

尝试检查是否已打开vForecastRecsCursor:

IF vForecastRecsCursor%ISOPEN THEN
  ...
END IF;

答案 1 :(得分:0)

您可以通过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;