ORA-06511:PL / SQL游标已经打开

时间:2013-02-04 23:47:45

标签: sql oracle plsql cursor

任何人都有任何关于系统告诉我PAR_CUR已经打开的原因的想法?一切都工作正常,直到我添加了最外面的光标(dup_cur),现在我收到了这个错误。感谢您的帮助。数据也在下面。

错误报告:

ORA-06511: PL/SQL: cursor already open
ORA-06512: at line 18
ORA-06512: at line 61
06511. 00000 -  "PL/SQL: cursor already open"
*Cause:    An attempt was made to open a cursor that was already open.
*Action:   Close cursor first before reopening.

CODE:

ACCEPT p_1 prompt 'PLEASE ENTER THE REGION:'
DECLARE
    v_child        regions.child_name%TYPE := '&p_1';
    v_parent       regions.parent_name%TYPE;
    v_parent2      regions.child_name%TYPE;
    v_parent3      regions.child_name%TYPE;
    v_count        NUMBER := 0;
    v_regionnumber NUMBER := 1;
    v_parentcount  NUMBER := 0;
    v_dup          regions.child_name%TYPE;
    CURSOR reg_cur IS
      SELECT Upper(parent_name)
      FROM   regions
      WHERE  Upper(child_name) = Upper(v_child)
             AND Upper(parent_name) = Upper(v_dup);
    CURSOR par_cur IS
      SELECT Upper(parent_name)
      FROM   regions
      WHERE  Upper(child_name) = v_parent
             AND parent_name IS NOT NULL;
    CURSOR dup_cur IS
      SELECT Upper(parent_name)
      FROM   regions
      WHERE  Upper(child_name) = Upper(v_child);

BEGIN         打开dup_cur;

    LOOP
        FETCH dup_cur INTO v_dup;
        EXIT WHEN dup_cur%NOTFOUND;

        SELECT Count(*)
        INTO   v_count
        FROM   regions
        WHERE  Upper(child_name) = Upper(v_child);

        SELECT Count(parent_name)
        INTO   v_parentcount
        FROM   regions
        WHERE  Upper(parent_name) = Upper(v_child);

        IF v_count > 0
            OR v_parentcount > 0 THEN
          SELECT Count(parent_name)
          INTO   v_count
          FROM   regions
          WHERE  Upper(child_name) = Upper(v_child);

          IF v_count > 0 THEN
            OPEN reg_cur;

            FETCH reg_cur INTO v_parent;

            dbms_output.Put_line('----- Begin Output -----');

            LOOP
                IF v_regionnumber < 2 THEN
                  dbms_output.Put_line('Line 1: (Region 1) '
                                       || Upper(v_child));

                  dbms_output.Put_line('Line 2: (Region 1) '
                                       || Upper(v_child)
                                       || ' --> '
                                       || '(Region 2) '
                                       || Upper (v_parent));
                END IF;

                OPEN par_cur;

                v_parent2 := v_parent;

                FETCH par_cur INTO v_parent;

                EXIT WHEN par_cur%NOTFOUND;

                v_regionnumber := v_regionnumber + 1;

                IF v_regionnumber = 2 THEN
                  dbms_output.Put_line('Line 3: '
                                       || '(Region 1) '
                                       || Upper(v_child)
                                       || ' --> '
                                       || '(Region 2) '
                                       || Upper(v_parent2)
                                       || ' --> '
                                       || '(Region 3) '
                                       || Upper(v_parent));
                ELSE
                  IF v_regionnumber = 3 THEN
                    dbms_output.Put_line('Line 4: '
                                         || '(Region 1) '
                                         || Upper(v_child)
                                         || ' --> '
                                         || '(Region 2) '
                                         || Upper(v_parent3)
                                         || ' --> '
                                         || '(Region 3) '
                                         || Upper(v_parent2)
                                         || ' --> '
                                         || '(Region 4) '
                                         || Upper(v_parent));
                  END IF;
                END IF;

                CLOSE par_cur;

                v_parent3 := v_parent2;
            END LOOP;

            dbms_output.Put_line('----- End_Output -----');

            CLOSE reg_cur;
          ELSE
            dbms_output.Put_line('----- Begin Output -----'
                                 || Chr(10)
                                 || 'Line 1: (Region 1) '
                                 || Upper(v_child)
                                 || Chr(10)
                                 || '----- End_Output -----');
          END IF;
        ELSE
          dbms_output.Put_line('----- Begin Output -----'
                               || Chr(10)
                               || Upper(v_child)
                               ||' is not in the table.'
                               || Chr(10)
                               || '----- End_Output -----');
        END IF;
    END LOOP;

    CLOSE dup_cur;
END; 




CREATE TABLE regions
(
        PARENT_NAME     VARCHAR2(30),
        CHILD_NAME      VARCHAR2(30)
);
INSERT INTO regions VALUES('Texas','Rockford');
INSERT INTO regions VALUES('Colorado','Aurora');
INSERT INTO regions VALUES(NULL,'Asia');
INSERT INTO regions VALUES(NULL,'Australia');
INSERT INTO regions VALUES(NULL,'Europe');
INSERT INTO regions VALUES(NULL,'North America');
INSERT INTO regions VALUES('Asia','China');
INSERT INTO regions VALUES('Asia','Japan');
INSERT INTO regions VALUES('Australia','New South Wales');
INSERT INTO regions VALUES('New South Wales','Sydney');
INSERT INTO regions VALUES('Canada','Ontario');
INSERT INTO regions VALUES('China','Beijing');
INSERT INTO regions VALUES('England','London');
INSERT INTO regions VALUES('Europe','United Kingdom');
INSERT INTO regions VALUES('Illinois','Aurora');
INSERT INTO regions VALUES('Illinois','Chicago');
INSERT INTO regions VALUES('Illinois','Rockford');
INSERT INTO regions VALUES('Wisconsin','Madison'); 
INSERT INTO regions VALUES('Japan','Osaka');
INSERT INTO regions VALUES('Japan','Tokyo');
INSERT INTO regions VALUES('North America','Canada');
INSERT INTO regions VALUES('North America','United States');
INSERT INTO regions VALUES('Ontario','Ottawa');
INSERT INTO regions VALUES('Ontario','Toronto');
INSERT INTO regions VALUES('United States','Colorado');
INSERT INTO regions VALUES('United States','Illinois');
INSERT INTO regions VALUES('United States','Texas');
INSERT INTO regions VALUES('United Kingdom','England'); 
COMMIT;

2 个答案:

答案 0 :(得分:8)

你在循环中打开和关闭光标。你应该在循环之外打开和关闭它。

FETCH REG_CUR INTO V_PARENT;
DBMS_OUTPUT.PUT_LINE('----- Begin Output -----');
OPEN PAR_CUR; -- ************OPEN HERE 
LOOP
  IF V_REGIONNUMBER < 2 THEN
    DBMS_OUTPUT.PUT_LINE('Line 1: (Region 1) ' || UPPER(V_CHILD));
    DBMS_OUTPUT.PUT_LINE('Line 2: (Region 1) ' || UPPER(V_CHILD) || ' --> ' || '(Region 2) ' || UPPER (V_PARENT));
  END IF;
  V_PARENT2 := V_PARENT;
  FETCH PAR_CUR INTO V_PARENT;
  EXIT WHEN PAR_CUR%NOTFOUND;
  V_REGIONNUMBER   := V_REGIONNUMBER + 1;
  IF V_REGIONNUMBER =2 THEN
    DBMS_OUTPUT.PUT_LINE('Line 3: ' || '(Region 1) '|| UPPER(V_CHILD) || ' --> ' || '(Region 2) ' || UPPER(V_PARENT2) || ' --> ' || '(Region 3) ' || UPPER(V_PARENT));
  ELSE
    IF V_REGIONNUMBER =3 THEN
      DBMS_OUTPUT.PUT_LINE('Line 4: ' || '(Region 1) '|| UPPER(V_CHILD) || ' --> ' || '(Region 2) ' || UPPER(V_PARENT3) || ' --> ' || '(Region 3) ' || UPPER(V_PARENT2)|| ' --> ' || '(Region 4) ' || UPPER(V_PARENT));
    END IF;
  END IF;
  V_PARENT3 := V_PARENT2;
END LOOP;
CLOSE PAR_CUR;-- ************CLOSE HERE

当你在循环中打开时,在第二次迭代中,游标错误已经打开

P.S。看起来你只是想弄清楚层次结构并将其打印出来。如果是这样,你可以这样做:

SQL> select ltrim(str, ' --> ') str
  2    from (select child_name, level, SYS_CONNECT_BY_PATH('(Region ' || level || ') ' || child_name, ' --> ') str,
  3                 parent_name
  4            from regions
  5           start with child_name = 'Rockford'
  6           connect by  child_name = prior parent_name)
  7   where parent_name is null
  8  /

STR
--------------------------------------------------------------------------------
(Region 1) Rockford --> (Region 2) Illinois --> (Region 3) United States --> (Re
gion 4) North America

(Region 1) Rockford --> (Region 2) Texas --> (Region 3) United States --> (Regio
n 4) North America


SQL> select ltrim(str, ' --> ') str
  2    from (select child_name, level, SYS_CONNECT_BY_PATH('(Region ' || level || ') ' || child_name, ' --> ') str,
  3                 parent_name
  4            from regions
  5           start with child_name = 'London'
  6           connect by  child_name = prior parent_name)
  7   where parent_name is null
  8  /

STR
--------------------------------------------------------------------------------
(Region 1) London --> (Region 2) England --> (Region 3) United Kingdom --> (Regi
on 4) Europe


SQL>

答案 1 :(得分:6)

它(通常)建议在打开任何游标时使用此语法

IF reg_cur %ISOPEN THEN
     CLOSE reg_cur ;
   END IF;
   OPEN reg_cur ;
希望这会有所帮助......