Ja, mange mennesker følger en dårlig praksis.
Dårlig stil
Jeg er enig med @Osy i, at OPEN/FETCH/CLOSE tilføjer helt unødvendig kode. Jeg vil gå endnu længere og sige, at du næsten aldrig skal bruge CURSOR
.
Først og fremmest vil du normalt gøre så meget som muligt i almindelig SQL. Hvis du skal bruge PL/SQL, skal du bruge en implicit markør. Det sparer dig for en linje kode og hjælper dig med at holde relateret logik tættere sammen.
Jeg er en stor tilhænger af at holde individuelle kodeenheder så små som muligt. Ved første øjekast virker det som en CURSOR
kan hjælpe dig med dette. Du kan definere din SQL øverst ét sted og derefter lave PL/SQL-looping senere.
Men i virkeligheden er det ekstra lag af indirekte næsten aldrig det værd. Nogle gange er der meget logik i SQL, og nogle gange er der meget logik i PL/SQL. Men i praksis giver det sjældent mening at lægge en masse kompleks logik i begge dele. Din kode ender normalt med at ligne en af disse:
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
eller:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
Uanset hvad, vil en af dine kodesektioner være meget lille. Kompleksiteten ved at adskille disse to sektioner af kode er større end kompleksiteten af en større, enkelt sektion af kode. (Men det er åbenbart min mening.)
Dårlig ydeevne
Der er betydelige præstationsimplikationer ved at bruge OPEN/FETCH/CLOSE. Den metode er meget langsommere end at bruge en cursor for loop eller en implicit cursor.
Compileren kan automatisk bruge bulk collect i nogle til loops. Men for at citere fra Oracle-præsentationen "PL/SQL-ydeevne – afsløring af myterne" , side 122:
Her er et hurtigt eksempel:
--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;
/