私は、コードのサブセクションをBEGIN ... ENDブロックで、それが正しいと思われるときに、やや無計画にグループ化してきました。ほとんどの場合、より長いストアドプロシージャで作業していて、一時変数が1つの場所に必要な場合は、コードのその部分に対してのみ宣言します。また、特定のコードに対してスローされた例外を識別して処理する場合にもこれを行います。
プロシージャ、関数、またはPL/SQLの別のより大きなブロック内にブロックをネストする必要がある他の理由はありますか?
次のようにローカルで例外を処理する場合:
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;
この例では、例外が処理されてから、次の従業員を続行して処理します。
もう1つの使用法は、次のようにスコープが制限されているローカル変数を宣言することです。
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;
ブロック内にのみ存在するデータに固有のプロシージャを作成する場合、ブロックをネストする傾向があります。不自然な例を次に示します。
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;
確かに、通常は必要ありませんが、本当に多くの場所からプロシージャを呼び出すことができる場合に便利です。
BEGIN/ENDブロックをネストする理由の1つは、コードの特定のローカルセクションの例外を処理し、例外が処理された場合に処理を続行できるようにするためです。