Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7645685
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T10:00:14+00:00 2026-05-31T10:00:14+00:00

I have a stored procedure that i thought was caught in an infinite loop,

  • 0

I have a stored procedure that i thought was caught in an infinite loop, but after taking it apart and running the various loops individually it turns out that my code is causing a

ORA-01000: maximum open cursors exceeded

The problem seems to occur with the way i am populating the first two cursors. This may seem like a dumb questions, but i was hoping someone could give me some advice on how to better handle the population of these cursors?

Below you will find my procedure in full, and i will then break down the area that seems to be causing the problem.

Full procedure:

    procedure SplitIntrvlsAtShiftBoundaries is

vRecCount number;
RC number;
vShiftIDAtIntervalStart number;
vShiftIDAtIntervalEnd number;
vDummyRecSecs number(6,4) := 0.0;

vStartTimestamp timestamp with time zone;
vEndTimestamp timestamp with time zone;

cCurs Sys_refcursor;

vCurrentRec TMP_SHIFT_LIST_TBL%rowtype;
vCurrentInterval MACHINE_INTERVAL%rowtype;
vNewInterval MACHINE_INTERVAL%rowtype;

lProcName    CONST.PBString;


vIntervalDOW smallint; -- intervals never span a midnite boundary 
                       -- are split over midnite in prior steps.

CURSOR C1 IS SELECT * FROM TMP_SHIFT_MI_TBL ORDER BY START_DATE_TIME ASC, MACHINE_ID;
CURSOR C2 IS SELECT * FROM TMP_SHIFT_LIST_TBL ORDER BY SHIFT_START_DAY ASC, SHIFT_START_TIME; 

BEGIN

  lProcName := 'TRANSFORM_PROCESS_2.SplitIntrvlsAtShiftBoundaries';
  pb_util.logdata(3, lProcName, 'Process Started ' );

  DELETE FROM TMP_SHIFT_MI_TBL;
  DELETE FROM TMP_SHIFT_LIST_TBL;

  INSERT INTO TMP_SHIFT_MI_TBL
  SELECT *
  FROM MACHINE_INTERVAL
  WHERE  interval_state = 0
  AND start_date_time <> CONST.STARTDATE
  AND  trunc(calc_end_time) < trunc( CONST.ENDDATE) - 144;

  BEGIN
    FOR R1 IN C1
      LOOP  

        -- gets the current interval from the machine interval table by using the interval id found from the tmp_table
        SELECT * INTO vCurrentInterval 
        FROM Machine_Interval MI 
        WHERE R1.Machine_Interval_ID = MI.Machine_Interval_Id; 

        -- gets the shifts containning the start and end dates obtained from the machine interval
        Shift_pkg.getShiftsContaining(R1.start_date_time, R1.calc_end_time, cCurs, vRecCount);

        FETCH cCurs INTO vCurrentRec;
          LOOP

            -- populates the tmp_shift_list_tbl dynamically
            BEGIN          
              EXIT WHEN cCurs%notfound;

              EXECUTE IMMEDIATE 'insert into tmp_shift_list_tbl
                                 (shift_id_pk, shift_name, shift_start_day, shift_start_time, 
                                  shift_end_day, shift_end_time, site_id_fk, shift_day_id,
                                  startoffset, endoffset) 
                           VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10)' 
                           USING vCurrentRec.SHIFT_ID_PK, vCurrentRec.SHIFT_NAME,
                                 vCurrentRec.SHIFT_START_DAY, vCurrentRec.SHIFT_START_TIME,
                                 vCurrentRec.SHIFT_END_DAY, vCurrentRec.SHIFT_END_TIME,
                                 vCurrentRec.SITE_ID_FK, vCurrentRec.SHIFT_DAY_ID, 
                                 vCurrentRec.STARTOFFSET, vCurrentRec.ENDOFFSET;

            END;
          END LOOP;  
          pb_util.logdata(3, lProcName, 'FOUND: ', 'found ' || vRecCount ||
                          ' shifts in machine interval: ' || R1.MACHINE_INTERVAL_ID);

        -- depending on the # of shifts found in vRecCount different cases are applied.
        CASE
        WHEN vRecCount = 1 -- apply shift id to interval   
           THEN 
             BEGIN             
               FOR R2 IN C2
                 LOOP

                    UPDATE MACHINE_INTERVAL MI
                    SET MI.SHIFT_ID = R2.SHIFT_ID_PK
                    WHERE MI.MACHINE_INTERVAL_ID = R1.MACHINE_INTERVAL_ID;

                 END LOOP;
             END;      
        WHEN vRecCount > 1 -- split up the interval between the shifts i.e. create intervals
           THEN 
            BEGIN            
              FOR R2 IN C2
                LOOP  

                  -- make copy of the current interval.
                  vNewInterval := vCurrentInterval;
                  -- set the new interval duration
                  vCurrentInterval.Interval_Duration := pb_util.intervaltosecond(R2.shift_Start_Time - 
                                                                                 vCurrentInterval.Start_Date_Time);
                  -- set the new shift id for the machine interval table
                  vCurrentInterval.Shift_ID := R2.Shift_ID_PK;

                  -- update the record.
                  DM.MachineIntervalRecordUpdate(MachineIntervalID => vCurrentInterval.Machine_Interval_ID,
                                                 StartDateTime => vCurrentInterval.Start_Date_Time,                                                 
                                                 IntervalDuration => vCurrentInterval.Interval_Duration,
                                                 IntervalCategory => vCurrentInterval.INTERVAL_CATEGORY,
                                                 NPTCategoryID => vCurrentInterval.NPT_CATEGORY_ID,
                                                 NPTControlledID => vCurrentInterval.CATEGORYTYPENUMERIC,
                                                 NPTOPStateID => vCurrentInterval.OPERATIONALSTATENUMERIC,
                                                 pExecutionSecs => vDummyRecsecs);

                  UPDATE MACHINE_INTERVAL MI
                  SET MI.Shift_ID = vCurrentInterval.Shift_ID
                  WHERE MI.Machine_Interval_ID = vCurrentInterval.Machine_Interval_ID;

                   -- set new start date time & interval duration                              
                  vNewInterval.Start_Date_Time := R2.Shift_End_Time;
                  vNewInterval.Interval_Duration := pb_util.intervaltosecond(vNewInterval.Calc_End_Time - 
                                                                             vNewInterval.Start_Date_Time);

                  -- create new record in interval table.
                  RC := DM.MachineIntervalRecordInsert(MachineIntervalRecord_IN => vNewInterval, 
                                                       pExecutionSecs => vDummyRecsecs);

                  -- set current interval to the newly created interval and loop.
                  vCurrentInterval := vNewInterval;

                END LOOP;
            END;      
        ELSE -- if no shifts are found then set id to null

          UPDATE MACHINE_INTERVAL MI
          SET SHIFT_ID = 0
          WHERE MI.MACHINE_INTERVAL_ID = R1.MACHINE_INTERVAL_ID;

        END CASE;   
      END LOOP;
      pb_util.logdata(3, lProcName, 'Process Completed ' );
      COMMIT;
  END;

exception when others then
pb_util.logdata(1, 'TRANSFORM_PROCESS_2.SplitIntrvlsAtShiftBoundaries', 'EXCEPTION THROWN (880B)', SQLERRM || ' STACK: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);

END SplitIntrvlsAtShiftBoundaries;

The cursors that i’m pretty sure is causing the problem are these two:

    CURSOR C1 IS SELECT * FROM TMP_SHIFT_MI_TBL ORDER BY START_DATE_TIME ASC, MACHINE_ID;
CURSOR C2 IS SELECT * FROM TMP_SHIFT_LIST_TBL ORDER BY SHIFT_START_DAY ASC, SHIFT_START_TIME; 

The area that the procedure seems to hit the maximum cursor opened exceeds:

 FOR R1 IN C1
  LOOP  

    -- gets the current interval from the machine interval table by using the interval id found from the tmp_table
    SELECT * INTO vCurrentInterval 
    FROM Machine_Interval MI 
    WHERE R1.Machine_Interval_ID = MI.Machine_Interval_Id; 

    -- gets the shifts containning the start and end dates obtained from the machine interval
    Shift_pkg.getShiftsContaining(R1.start_date_time, R1.calc_end_time, cCurs, vRecCount);

    FETCH cCurs INTO vCurrentRec;
      LOOP

        -- populates the tmp_shift_list_tbl dynamically
        BEGIN          
          EXIT WHEN cCurs%notfound;

          EXECUTE IMMEDIATE 'insert into tmp_shift_list_tbl
                             (shift_id_pk, shift_name, shift_start_day, shift_start_time, 
                              shift_end_day, shift_end_time, site_id_fk, shift_day_id,
                              startoffset, endoffset) 
                       VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10)' 
                       USING vCurrentRec.SHIFT_ID_PK, vCurrentRec.SHIFT_NAME,
                             vCurrentRec.SHIFT_START_DAY, vCurrentRec.SHIFT_START_TIME,
                             vCurrentRec.SHIFT_END_DAY, vCurrentRec.SHIFT_END_TIME,
                             vCurrentRec.SITE_ID_FK, vCurrentRec.SHIFT_DAY_ID, 
                             vCurrentRec.STARTOFFSET, vCurrentRec.ENDOFFSET;

        END;
      END LOOP;  
      pb_util.logdata(3, lProcName, 'FOUND: ', 'found ' || vRecCount ||
                      ' shifts in machine interval: ' || R1.MACHINE_INTERVAL_ID);
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T10:00:15+00:00Added an answer on May 31, 2026 at 10:00 am

    Implicit cursors will never generate an ORA-01000 error because Oracle takes care of closing them when they go out of scope.

    The problem in your code is with cCurs. Shift_pkg.getShiftsContaining opens the cursor and your code fetches from the cursor. But there is no code to close the cursor when you are done fetching from it. Your code will need to close the cursor when you are done fetching from it.

    The code itself is a little confusing. Normally, you’d fetch from a cursor inside a loop. The code that you’ve posted, however, has the fetch occurring outside of the loop which means that you’ll have an infinite loop if cCurs returns a row. So either cCurs never returns any data when you FETCH from it or you’ve got an infinite loop or the code you’ve posted isn’t exactly what you’re actually running.

    Normally, you’d have something like this which will fetch from the cursor in a loop, exit the loop when no more rows are available, and then close the cursor.

    LOOP
      FETCH cCurs INTO vCurrentRec;
      EXIT WHEN cCurs%notfound;
    
      EXECUTE IMMEDIATE 'insert into tmp_shift_list_tbl
                         (shift_id_pk, shift_name, shift_start_day, shift_start_time, 
                          shift_end_day, shift_end_time, site_id_fk, shift_day_id,
                          startoffset, endoffset) 
                   VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10)' 
                   USING vCurrentRec.SHIFT_ID_PK, vCurrentRec.SHIFT_NAME,
                         vCurrentRec.SHIFT_START_DAY, vCurrentRec.SHIFT_START_TIME,
                         vCurrentRec.SHIFT_END_DAY, vCurrentRec.SHIFT_END_TIME,
                         vCurrentRec.SITE_ID_FK, vCurrentRec.SHIFT_DAY_ID, 
                         vCurrentRec.STARTOFFSET, vCurrentRec.ENDOFFSET;
    END LOOP;
    
    CLOSE cCurs;
    

    That being said, there doesn’t appear to be any reason to use dynamic SQL here. It would also be helpful to choose more meaningful names for your variables: C1, R1, C2, R2, and cCurs are not exactly meaningful names. And you’ll generally want to break up your code into smaller blocks that are easier to read and digest.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a problem where it seems that when running the same stored procedure
i have a stored procedure that i tested directly and it works, but when
I have a stored procedure that uses a FAST_FORWARD cursor to chronologically loop over
I have a strange, sporadic issue. I have stored procedure that returns back 5
I have a stored procedure that consists of a single select query used to
I have a stored procedure that returns multiple tables. How can I execute and
I have a stored procedure that looks like: CREATE PROCEDURE dbo.usp_TestFilter @AdditionalFilter BIT =
I have a Stored Procedure that rolls-back a series of operations. I want to
I have a stored procedure that returns values from a temp table. In my
I have a stored procedure that needs to convert hexadecimal numbers to their decimal

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.