sql >> Base de Datos >  >> RDS >> Oracle

¿Es una mala práctica usar la instrucción EXIT WHEN al recorrer los CURSORES en Oracle?

Sí, muchas personas están siguiendo una mala práctica.

Mal estilo

Estoy de acuerdo con @Osy en que OPEN/FETCH/CLOSE agrega un código completamente innecesario. Iría aún más lejos y diría que casi nunca deberías usar CURSOR .

En primer lugar, normalmente desea hacer todo lo posible en SQL simple. Si necesita usar PL/SQL, use un cursor implícito. Le ahorrará una línea de código y le ayudará a mantener la lógica relacionada más unida.

Creo firmemente en mantener las unidades de código individuales lo más pequeñas posible. A primera vista, parece un CURSOR puede ayudarte a hacer esto. Puede definir su SQL en la parte superior en un solo lugar y luego hacer el bucle PL/SQL más tarde.

Pero en realidad, esa capa adicional de indirección casi nunca vale la pena. A veces, mucha lógica está en SQL y, a veces, mucha lógica está en PL/SQL. Pero en la práctica, rara vez tiene sentido poner mucha lógica compleja en ambos. Su código generalmente termina pareciéndose a uno de estos:

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

o:

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

De cualquier manera, una de sus secciones de código será muy pequeña. La complejidad de separar esas dos secciones de código es mayor que la complejidad de una sola sección de código más grande. (Pero esa es obviamente mi opinión).

Mal rendimiento

Existen importantes implicaciones de rendimiento con el uso de OPEN/FETCH/CLOSE. Ese método es mucho más lento que usar un cursor for loop o un cursor implícito.

El compilador puede usar automáticamente la recopilación masiva en algunos bucles for. Pero, para citar la presentación de Oracle "Rendimiento de PL/SQL:derribando los mitos" , página 122:

He aquí un ejemplo rápido:

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