sql >> Databasteknik >  >> RDS >> Oracle

Är det en dålig praxis att använda EXIT WHEN-instruktionen när man går igenom CURSORs i Oracle?

Ja, många människor följer en dålig praxis.

Dålig stil

Jag håller med @Osy om att OPEN/FETCH/CLOSE lägger till helt onödig kod. Jag skulle gå ännu längre och säga att du nästan aldrig ska använda CURSOR .

Först och främst vill du normalt göra så mycket som möjligt i vanlig SQL. Om du behöver använda PL/SQL, använd en implicit markör. Det sparar dig en rad kod och hjälper dig att hålla relaterad logik närmare varandra.

Jag tror starkt på att hålla enskilda kodenheter så små som möjligt. Vid första anblicken verkar det som en CURSOR kan hjälpa dig att göra detta. Du kan definiera din SQL upptill på ett ställe och sedan göra PL/SQL-loopen senare.

Men i verkligheten är det där extra lagret av inriktning nästan aldrig värt det. Ibland finns mycket logik i SQL, och ibland finns mycket logik i PL/SQL. Men i praktiken är det sällan meningsfullt att lägga mycket komplex logik i båda. Din kod slutar vanligtvis med att se ut som någon av dessa:

for records in (<simple SQL>) loop
    <complex PL/SQL>
end loop;

eller:

for records in
(
    <complex SQL>
) loop
    <simple PL/SQL>;
end loop;

Hur som helst kommer en av dina kodsektioner att vara väldigt liten. Komplexiteten i att separera dessa två kodsektioner är större än komplexiteten för en större, enskild kodsektion. (Men det är uppenbarligen min åsikt.)

Dåligt resultat

Det finns betydande prestandaimplikationer med att använda OPEN/FETCH/CLOSE. Den metoden är mycket långsammare än att använda en markör för loop eller en implicit markör.

Kompilatorn kan automatiskt använda bulk collect i vissa för loopar. Men för att citera från Oracle-presentationen "PL/SQL Performance—Debunking the Myths" , sid 122:

Här är ett snabbt exempel:

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


  1. Hämtar länkad lista i MySQL-databas

  2. Koppla från nod JS mysql databas

  3. Uppföljningsgräns och kompensera felaktig placering i frågan

  4. Hur man ansluter Amazon RDS i iOS