Cursor running indefinitely

时间:2015-11-12 11:15:17

标签: oracle plsql cursor

I wrote a simple cursor in SQL like below.Here i am expecting that it will fetch all the rows from test and as per the row count,hard coded values will be added in test2 table.

DECLARE
  CURSOR customers is
    SELECT * FROM test;
BEGIN
  OPEN customers;
  LOOP
    insert into test2 values (2, 3, 3);
  END LOOP;
  CLOSE customers;
END;
/

When I am executing it in sql prompt,it's running indefinitely. What am I doing wrong here?

3 个答案:

答案 0 :(得分:3)

You can use FOR LOOP:

DECLARE
  CURSOR customers IS
     SELECT * FROM test;
BEGIN
  FOR i IN customers
  LOOP
     insert into test2 values (2, 3, 3);
  END LOOP;
END;
/

or you need to add EXIT CONDITION becuase your loop is (indefinite):

DECLARE  
  CURSOR customers is
    SELECT * FROM test;

  l_customer customers%ROWTYPE;
BEGIN
  OPEN customers;
  LOOP
    FETCH customers INTO l_customer;
    EXIT WHEN customers%NOTFOUND;

    insert into test2 values (2, 3, 3);
  END LOOP;
  CLOSE customers;
END;
/

EDIT:

As Lalit Kumar B mentioned in the comment, you can use:

BEGIN
   FOR i IN (SELECT * FROM test)
   LOOP
       insert into test2 values (2, 3, 3);
   END LOOP;
END;

For more info read Working with Cursors by Steven Feuerstein

答案 1 :(得分:3)

I would rather avoid using an explicit cursor and use a cursor for loop.

BEGIN
  FOR i IN
  (SELECT * FROM test
  )
  LOOP
    <do something>
    INSERT INTO test2 VALUES ...;
  END LOOP;
END;
/

Remember, a loop would do the insert row-by-row a.k.a. slow-by-slow.

As @Boneist mentioned, there is a reason why the cursor for loop is better over the explicit cursor. In the recent Oracle versions, it is optimized in a better way by doing a bulk collect limit 100 internally.

But, it's not just about bulk collecting, we are dealing with the operations we would subsequently do on the array that we have fetched incrementally. We could further improve the performance by using FORALL statement along with BULK COLLECT.

IMO, the best would be do it in pure SQL using INSERT INTO table SELECT... There are lot of other factors, but it wouldn't be in the scope of OP's question.

答案 2 :(得分:2)

I think the way your using cursors is not correct. In below i have edited your code.. And you need to add exit condition for terminating loop.

DECLARE
  CURSOR customers is
    SELECT * FROM test;
   cus2  customers%rowtype;
BEGIN
  OPEN customers;
  LOOP
  FETCH customers INTO cus2;
  EXIT WHEN customers%NOTFOUND;
    insert into test2 values (2, 3, 3);
  END LOOP;
  CLOSE customers;
END;
/

Modify the above block based on your requirement.