Ja, veel mensen volgen een slechte gewoonte.
Slechte stijl
Ik ben het met @Osy eens dat OPEN/FETCH/CLOSE volledig onnodige code toevoegt. Ik zou zelfs nog verder gaan en zeggen dat je bijna nooit CURSOR
. moet gebruiken .
Allereerst wil je normaal gesproken zoveel mogelijk in gewone SQL doen. Als je PL/SQL moet gebruiken, gebruik dan een impliciete cursor. Het bespaart u een regel code en helpt u gerelateerde logica dichter bij elkaar te houden.
Ik ben er een groot voorstander van om individuele code-eenheden zo klein mogelijk te houden. Op het eerste gezicht lijkt het een CURSOR
kan u hierbij helpen. U kunt uw SQL bovenaan op één plaats definiëren en later de PL/SQL-looping uitvoeren.
Maar in werkelijkheid is die extra laag indirectheid bijna nooit de moeite waard. Soms zit er veel logica in SQL, en soms zit er veel logica in PL/SQL. Maar in de praktijk heeft het zelden zin om in beide veel complexe logica te stoppen. Je code ziet er meestal zo uit:
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
of:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
Hoe dan ook, een van uw codesecties zal erg klein zijn. De complexiteit van het scheiden van die twee codesecties is groter dan de complexiteit van een grotere, enkele codesectie. (Maar dat is natuurlijk mijn mening.)
Slechte prestatie
Er zijn aanzienlijke prestatie-implicaties bij het gebruik van OPEN/FETCH/CLOSE. Die methode is veel trager dan het gebruik van een cursor voor lus of een impliciete cursor.
De compiler kan in sommige for-lussen automatisch bulkcollect gebruiken. Maar om te citeren uit de Oracle-presentatie "PL/SQL-prestaties:de mythes ontkrachten" , pagina 122:
Hier is een snel voorbeeld:
--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;
/