ORA-06511:PL / SQL:游标已经打开即使关闭后也是如此

时间:2016-06-13 13:34:59

标签: oracle plsql oracle-sqldeveloper

我创建了一个程序包,其程序如下:

 PROCEDURE person_phone_data_load
   IS
      CURSOR cur_phone_info
      is
         SELECT itnpi.ROWID row_id, itnpi.*
           from xx_TAL_NEWHIRE_PHONE_INT ITNPI,
             xx_tal_newhire_employ_int emp
          where 1 = 1 and ITNPI.STATUS in ('N', 'E')
               and EMP.CANDIDATE_NUMBER=ITNPI.CANDIDATE_NUMBER
            and BUSINESS_UNIT='APGEN BUSINESS GROUP'
          ;
/**
select phone.ROWID row_id, phone.candidate_number, DECODE(phone.phone_type,'Work Phone','WORK','Home Phone','HOME','Cellular Phone','MOBILE',phone.phone_type) PHONE_TYPE,
       case phone.phone_type
           when 'Mobile Phone' then mobile_number
           when 'Work Phone'   then WORK_PHONE 
           when 'Home Phone'   then home_number
           end   as phone_number
from xx_tal_newhire_phone_int phone
 Where 1 = 1 And Phone.Status In ('N', 'E'); 
 **/
      CURSOR lcu_get_person_id (p_candidate_number VARCHAR2)
      IS
         SELECT   papf.person_id, papf.start_date
             FROM per_all_people_f papf, per_people_extra_info ppei
            WHERE papf.person_id = ppei.person_id
              AND ppei.information_type = 'XXHR_TAL_NEWHIRE_READER'
              AND ppei.pei_information1 = p_candidate_number
              AND papf.effective_start_date =
                                    (SELECT MAX (papf1.effective_start_date)
                                       FROM per_all_people_f papf1
                                      WHERE papf1.person_id = papf.person_id)
         GROUP BY papf.person_id, papf.start_date;

      CURSOR lcu_check_phone (p_personid NUMBER, p_phone_type VARCHAR2)
      IS
         SELECT phone_number
           FROM per_phones
          WHERE SYSDATE BETWEEN date_from AND NVL (date_to, '31-DEC-4712')
            AND phone_type = p_phone_type
            AND parent_id = p_personid;

      lv_phone_type              VARCHAR2 (240);
      ln_phone_type_excep        VARCHAR2 (2000);
      an_phone_type_excep        VARCHAR2 (2000);
      ln_phone_id                NUMBER;
      ln_object_version_number   NUMBER;
      ld_ph_date_from            DATE;
      ld_ph_date_to              DATE;
      lv_phone_number            VARCHAR2 (100);    

      ln_person_id               NUMBER;
      ln_phone_err_msg           VARCHAR2 (2000);
      ln_person_excep            VARCHAR2 (2000);
      an_person_excep            VARCHAR2 (2000);
      lc_rec_status              VARCHAR2 (1);
      ln_phoneno                 NUMBER;
      ln_start_date               DATE;
   BEGIN
      fnd_file.put_line (fnd_file.LOG,
                         '**********************************************'
                        );
      fnd_file.put_line (fnd_file.LOG,
                         '** New Hire Phone load Program Starts **'
                        );

      FOR phone_info_rec IN cur_phone_info
      LOOP
         BEGIN
            lv_phone_type := NULL;
            ln_phone_id := NULL;
            ln_object_version_number := NULL;
            ln_person_id := NULL;
            ln_phone_err_msg := NULL;
            ld_ph_date_from := TRUNC (SYSDATE);
            ld_ph_date_to := NULL;
            lv_phone_number := phone_info_rec.phone_number ;

            ln_phone_type_excep := NULL;
            ln_person_excep := NULL;
            lc_rec_status := 'S';

            IF phone_info_rec.phone_type IS NOT NULL
            THEN
               lv_phone_type :=
                     get_lookup_code ('PHONE_TYPE', phone_info_rec.phone_type);

               IF lv_phone_type = 'NO_VALUE'
               THEN
                  lc_rec_status := 'E';
                  -- Could not decode the SEX for the Employee.
                  ln_phone_err_msg :=
                        ln_phone_err_msg
                     || 'Invalid Phone Type for candidate_number: '
                     || phone_info_rec.candidate_number
                     || ' # ';
               END IF;
            END IF;

            IF phone_info_rec.candidate_number IS NOT NULL
            THEN
               ln_person_id := NULL;

               OPEN lcu_get_person_id (phone_info_rec.candidate_number);

               FETCH lcu_get_person_id
                INTO ln_person_id, ln_start_date;

               CLOSE lcu_get_person_id;

               IF ln_person_id IS NULL
               THEN
                  lc_rec_status := 'E';
                  -- Employee Not Created for the Candidate Number.
                  ln_phone_err_msg :=
                        ln_phone_err_msg
                     || 'Employee Record not created for the candidate_number: '
                     || phone_info_rec.candidate_number
                     || ' # ';
               ELSIF ln_person_id IS NOT NULL
               THEN
                  OPEN lcu_check_phone (ln_person_id, lv_phone_type);

                  FETCH lcu_check_phone
                   Into Ln_Phoneno;
   Close lcu_check_phone;

         If Lcu_Check_Phone%Isopen Then
                        Close Lcu_Check_Phone;
                        END IF; 
                  IF ln_phoneno = phone_info_rec.phone_number
                  Then
                     lc_rec_status := 'P';
                     ln_phone_err_msg :=
                           ln_phone_err_msg
                        || 'Phone already exists for the candidate_number:  '
                        || phone_info_rec.candidate_number
                        || ' # ';


                  END IF;


               END IF;
            ELSE
               lc_rec_status := 'E';
               -- Candidate Number is NULL.
               ln_phone_err_msg :=
                     ln_phone_err_msg
                  || 'Candidate Number is NULL; So Could not find the Employee for Address creation';
            END IF;

            IF lc_rec_status = 'S'
            THEN
               BEGIN

                  UPDATE xx_tal_newhire_phone_int iph
                     SET status = 'P',
                         error_msg = NULL
                   WHERE iph.ROWID = phone_info_rec.row_id;

                  COMMIT;
                  fnd_file.put_line
                     (fnd_file.LOG,
                         'Successfully Processed phone record for candidate_number: '
                      || phone_info_rec.candidate_number
                     );
               EXCEPTION
                  WHEN OTHERS
                  THEN
                     ln_phone_err_msg :=
                           'Phone API Error while processing candidate_number: '
                        || phone_info_rec.candidate_number
                        || ' , '
                        || SUBSTR (SQLERRM, 1, 150);

                     UPDATE xx_tal_newhire_phone_int iph
                        SET status = 'E',
                            error_msg = ln_phone_err_msg
                      WHERE iph.ROWID = phone_info_rec.row_id;

                     fnd_file.put_line
                        (fnd_file.LOG,
                            'Person API Error while processing candidate_number: '
                         || phone_info_rec.candidate_number
                         || ' , '
                         || SUBSTR (SQLERRM, 1, 150)||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE()
                        );
               END;
            ELSE
               UPDATE xx_tal_newhire_phone_int iph
                  SET status = lc_rec_status,
                      error_msg = ln_phone_err_msg
                WHERE iph.ROWID = phone_info_rec.row_id;
            END IF;

            COMMIT;
         EXCEPTION
            WHEN OTHERS
            THEN
               ln_phone_err_msg :=
                                 'Phone Error : ' || SUBSTR (SQLERRM, 1, 150)||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE();

               Update xx_Tal_Newhire_Phone_Int Iph
                  SET status = 'E',
                      error_msg = ln_phone_err_msg
                WHERE iph.ROWID = phone_info_rec.row_id;

               COMMIT;
         END;
      End Loop;

      fnd_file.put_line (fnd_file.LOG,
                         '** New Hire Phone load Program Ends **'
                        );
   EXCEPTION
      WHEN OTHERS
      THEN
         fnd_file.put_line (fnd_file.LOG,
                            'In phone main :' || SUBSTR (SQLERRM, 1, 150)
                           );
         ROLLBACK;
   END person_phone_data_load;

我得到的是:"Phone Error : ORA-06511: PL/SQL: cursor already open

日志中的

错误。这适用于光标lcu_check_phone。我还明确添加了一个if语句,以便在打开时关闭游标。我仍然得到这个错误。

2 个答案:

答案 0 :(得分:3)

我认为你遇到的问题是这个

              OPEN lcu_check_phone (ln_person_id, lv_phone_type);

              FETCH lcu_check_phone
               Into Ln_Phoneno;
              Close lcu_check_phone;

电话号码不是数字字段 - 但Ln_Phoneno定义为数字。你的fetch语句抛出了一个被处理的异常,但这会绕过你的两个close语句。然后在下一次迭代中,您无法重新打开光标。

如果你要拥有所有这些嵌套循环,那么你需要在异常处理程序中放置close语句。

替代方案是更加模块化 - 使用许多小程序来分解你的代码 - 然后你不必担心范围这么多,因为每个游标只会在一次迭代的持续时间内存在。如果这是有道理的......

答案 1 :(得分:1)

要避免打开/关闭/获取游标问题,请尽可能使用游标循环。您不必担心在一次获取中从游标中获取所有值以及关于循环计数,因为它本身是由循环控制的(例如:来自其他语言的每个循环)。我通常使用标准的open / fetch / close来检查游标是否加载了一些数据,当它没有将%NOTFOUND标志设置为true时,例如在错误处理中,如果没有选择任何数据,则选择投入NO_DATA_FOUND