Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Ist es eine schlechte Praxis, die EXIT WHEN-Anweisung zu verwenden, wenn CURSORs in Oracle durchlaufen werden?

Ja, viele Leute folgen einer schlechten Praxis.

Schlechter Stil

Ich stimme @Osy zu, dass OPEN/FETCH/CLOSE völlig unnötigen Code hinzufügt. Ich würde sogar noch weiter gehen und sagen, dass Sie CURSOR fast nie verwenden sollten .

Zunächst einmal möchten Sie normalerweise so viel wie möglich in einfachem SQL erledigen. Wenn Sie PL/SQL verwenden müssen, verwenden Sie einen impliziten Cursor. Es erspart Ihnen eine Codezeile und hilft Ihnen, die zugehörige Logik näher beieinander zu halten.

Ich glaube fest daran, einzelne Codeeinheiten so klein wie möglich zu halten. Auf den ersten Blick sieht es aus wie ein CURSOR kann Ihnen dabei helfen. Sie können Ihr SQL oben an einer Stelle definieren und die PL/SQL-Schleife später ausführen.

Aber in Wirklichkeit lohnt sich diese zusätzliche indirekte Ebene fast nie. Manchmal steckt viel Logik in SQL und manchmal viel Logik in PL/SQL. Aber in der Praxis macht es selten Sinn, viel komplexe Logik in beide zu stecken. Ihr Code sieht normalerweise so aus:

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

oder:

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

In jedem Fall wird einer Ihrer Codeabschnitte sehr klein sein. Die Komplexität der Trennung dieser beiden Codeabschnitte ist größer als die Komplexität eines größeren einzelnen Codeabschnitts. (Aber das ist natürlich meine Meinung.)

Schlechte Leistung

Die Verwendung von OPEN/FETCH/CLOSE hat erhebliche Auswirkungen auf die Leistung. Diese Methode ist viel langsamer als einen Cursor für eine Schleife oder einen impliziten Cursor zu verwenden.

Der Compiler kann in einigen for-Schleifen automatisch die Massenerfassung verwenden. Aber um aus der Oracle-Präsentation zu zitieren "PL/SQL-Leistung – Mythen entlarven" , Seite 122:

Hier ist ein kurzes Beispiel:

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