sql >> Database >  >> RDS >> Oracle

Is het een slechte gewoonte om de instructie EXIT WHEN te gebruiken bij het doorlopen van CURSOR's in Oracle?

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


  1. MySQL-resultaten op IN-volgorde bestellen?

  2. Hoe LISTAGG te gebruiken om rijen met aanhalingstekens te retourneren

  3. Hoe voeg je een tabel toe aan deze SQL-code?

  4. PostgreSQL-afstemming:belangrijke dingen om de prestaties te verbeteren