光标 运行 无限期
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的问题范围内。
我在 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的问题范围内。