2010-02-25 24 views
14

He estado agrupando subdivisiones de código en bloques BEGIN ... END cuando parece correcto. Sobre todo cuando estoy trabajando en un procedimiento almacenado más largo y hay una necesidad de una variable temporal en un lugar, lo declararé solo para esa parte del código. También hago esto cuando quiero identificar y manejar excepciones arrojadas por una pieza específica de código.¿Cuándo debo anidar los bloques PL/SQL BEGIN ... END?

¿Alguna otra razón por la cual uno debe anidar bloques dentro de un procedimiento, función u otro bloque más grande de PL/SQL?

Respuesta

17

Cuando se quiere controlar las excepciones a nivel local como esto:

begin 
    for emp_rec in (select * from emp) loop 
     begin 
     my_proc (emp_rec); 
     exception 
     when some_exception then 
      log_error('Failed to process employee '||emp_rec.empno); 
     end; 
    end loop; 
end; 

En este ejemplo, la excepción se maneja y luego continuar y procesar el siguiente empleado.

Otro uso es para declarar variables locales que tienen un alcance limitado de esta manera:

declare 
    l_var1 integer; 
    -- lots of variables 
begin 
    -- lots of lines of code 
    ... 
    for emp_rec in (select * from emp) loop 
     declare 
     l_localvar integer := 0; 
     begin 
     -- Use l_localvar 
     ... 
     end 
    end loop; 

end; 

Eso sí, con ganas de hacer esto es a menudo una señal de que su programa es demasiado grande y debe ser disuelta:

declare 
    l_var1 integer; 
    -- lots of variables 
    ... 
    procedure local_proc (emp_rec emp%rowtype): 
     l_localvar integer := 0; 
    begin 
     -- Use l_localvar 
     ... 
    end 
begin 
    -- lots of lines of code 
    ... 
    for emp_rec in (select * from emp) loop 
     local_proc (emp_rec); 
    end loop; 

end; 
+1

+1. La mejor práctica para los bloques 'begin/end' es bloques anónimos, bloques con nombre (procedimiento/función) o para manejar excepciones específicas, como en el primer ejemplo. Anidando una declaración 'declare' dentro de un bloque' begin/end', yo llamaría a un error de programación, porque introduce la posibilidad de colisiones de alcance variable, y esos son difíciles de depurar. –

1

Tiendo a anidar bloques cuando quiero crear procedimientos que son específicos para los datos que solo existen dentro del bloque. Aquí es un ejemplo artificial:

BEGIN 
    FOR customer IN customers LOOP 
    DECLARE 

     PROCEDURE create_invoice(description VARCHAR2, amount NUMBER) IS 
     BEGIN 
     some_complicated_customer_package.create_invoice(
      customer_id => customer.customer_id, 
      description => description, 
      amount => amount 
     ); 
     END; 

    BEGIN 

     /* All three calls are being applied to the current customer, 
     even if we're not explicitly passing customer_id. 
     */ 
     create_invoice('Telephone bill', 150.00); 
     create_invoice('Internet bill', 550.75); 
     create_invoice('Television bill', 560.45); 

    END; 
    END LOOP; 
END; 

Por supuesto, normalmente no es necesario, pero ha llegado en muy útil cuando un procedimiento se puede llamar desde muchos lugares.

+0

No veo la necesidad, ya estás dentro de un ciclo. En segundo lugar, ¿no debería la declaración del procedimiento almacenado ocurrir fuera del ciclo? –

+0

@OMG Ponies: El propósito de este ejemplo fue ilustrar el hecho de que es posible declarar procedimientos dentro de un bloque para aprovechar los datos de ese bloque sin tener que pasar la información a través de parámetros. Está en lo cierto, si quiere pasar explícitamente 'customer_id' como parámetro a' create_invoice', debería declararse fuera del ciclo. En mi experiencia, me encontré con situaciones en las que es más claro aprovechar la información del bloque. –

0

Una razón para tener bloques BEGIN/END anidados es ser capaz de manejar excepciones para una sección local específica del código y, potencialmente, continuar el procesamiento si se procesa la excepción.

Cuestiones relacionadas