是的,很多人都在遵循一种不好的做法。
坏作风
我同意@Osy 的观点,即 OPEN/FETCH/CLOSE 添加了完全不必要的代码。我会更进一步,说你几乎不应该使用CURSOR
.
首先,您通常希望尽可能多地使用纯 SQL。如果您需要使用 PL/SQL,请使用隐式游标。它将为您节省一行代码,并帮助您将相关逻辑更紧密地联系在一起。
我坚信保持单个代码单元尽可能小。乍一看,它似乎CURSOR
可以帮助您做到这一点。你可以在一个地方定义你的 SQL,然后再做 PL/SQL 循环。
但实际上,额外的间接层几乎不值得。有时很多逻辑在 SQL 中,有时很多逻辑在 PL/SQL 中。但在实践中,在两者中加入大量复杂逻辑几乎没有意义。您的代码通常最终看起来像以下之一:
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
或者:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
无论哪种方式,您的代码部分之一都将非常小。分离这两个代码部分的复杂性大于更大的单个代码部分的复杂性。(但这显然是我的意见。)
表现不佳
使用 OPEN/FETCH/CLOSE 会对性能产生重大影响。该方法比使用游标循环或隐式游标慢得多。
编译器可以在某些 for 循环中自动使用批量收集。但是,引用 Oracle 演示文稿“PL/SQL 性能——揭穿神话”,第 122 页:
不要通过使用 open、fetch 循环、close 形式放弃这个机会
这是一个简单的例子:
--Sample data
create table t(a number, b number);
insert into t select level, level from dual connect by level <= 100000;
commit;
--OPEN/FETCH/CLOSE
--1.5 seconds
declare
cursor test_cur is
select a, b from t;
test_rec test_cur%rowtype;
counter number;
begin
open test_cur;
loop
fetch test_cur into test_rec;
exit when test_cur%notfound;
counter := counter + 1;
end loop;
close test_cur;
end;
/
--Implicit cursor
--0.2 seconds
declare
counter number;
begin
for test_rec in (select a, b from t) loop
counter := counter + 1;
end loop;
end;
/