Когда я должен вставлять PL/SQL BEGIN... END блоки?

Я несколько бессистемно группировал подразделы кода в BEGIN... END блокирует, когда кажется правильным. В основном, когда я работаю над более длинной хранимой процедурой и там нужна временная переменная в одном месте, я объявлю ее только для этой части кода. Я также делаю это, когда хочу идентифицировать и обрабатывать исключения, создаваемые для определенной части кода.

Любые другие причины, по которым нужно блокировать блоки внутри процедуры, функции или другого более крупного блока PL/SQL?

Ответ 1

Если вы хотите обрабатывать исключения локально следующим образом:

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;

В этом примере обрабатывается исключение, а затем мы продолжаем и обрабатываем следующего сотрудника.

Другое использование - объявить локальные переменные, которые имеют ограниченную область видимости:

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;

Помните, что желание сделать это часто является признаком того, что ваша программа слишком большая и должна быть разбита:

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; 

Ответ 2

Я склонен блокировать блоки, когда хочу создавать процедуры, специфичные для данных, которые существуют только внутри блока. Вот надуманный пример:

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;

Конечно, это обычно не требуется, но это очень удобно, когда процедуру можно вызвать из многих мест.

Ответ 3

Одна из причин наличия вложенных блоков BEGIN/END заключается в том, чтобы обрабатывать исключения для определенного локального раздела кода и потенциально продолжать обработку, если обрабатывается исключение.