光标 运行 无限期

Cursor running indefinitely

我在 SQL 中写了一个简单的游标,比如 below.Here 我希望它能从测试中获取所有行,并且根据行数,硬编码值将添加到 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;
/

当我在 sql 提示符下执行时,它会无限期地 运行。 我在这里做错了什么?

我认为您使用游标的方式不正确。在下面我编辑了你的代码。你需要添加终止循环的退出条件。

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;
/

根据您的要求修改上述块。

您可以使用 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;
/

或者您需要添加 EXIT CONDITION 因为您的循环是(不确定的):

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;
/

编辑:

如评论中所述,您可以使用:

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

有关详细信息,请阅读 Working with Cursors by Steven Feuerstein

我宁愿避免使用 显式游标 并使用 循环游标 .

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

请记住,循环会执行插入 逐行 a.k.a。 慢慢来

正如@Boneist 提到的,cursor for loop 优于显式游标是有原因的。在最近的 Oracle 版本中,通过在内部执行 bulk collect limit 100 以更好的方式对其进行了优化。

但是,这不仅仅是关于 批量收集,我们正在处理我们随后将在我们拥有的数组上执行的 操作 获取 增量。我们可以通过使用 FORALL 语句和 BULK COLLECT 来进一步提高性能。

IMO,最好是使用 INSERT INTO table SELECT.. 在纯 SQL 中完成。还有很多其他因素,但这不在OP的问题范围内。