PL/SQLでは、処理をブロック単位で構成するのが基本ですが、そのブロックの中にさらに別のブロックを定義することができます。これをネストされたブロック(入れ子ブロック)と呼びます。
この記事では、PL/SQLでのネストブロックの書き方と、各ブロックで宣言された変数や例外のスコープ(有効範囲)について、初心者にもわかりやすく解説します。
ネストブロックとは?
PL/SQLでは、BEGIN〜ENDで囲まれた処理単位を「ブロック」と呼びます。ネストブロックとは、その中にさらに別のブロックを定義することを指します。これにより、処理を細分化し、局所的な変数や例外処理を持たせることができます。
ネストブロックの基本構文
DECLARE
outer_var VARCHAR2(50) := '外部ブロック';
BEGIN
DBMS_OUTPUT.PUT_LINE(outer_var); -- OK
DECLARE
inner_var VARCHAR2(50) := '内部ブロック';
BEGIN
DBMS_OUTPUT.PUT_LINE(inner_var); -- OK
DBMS_OUTPUT.PUT_LINE(outer_var); -- OK(外側の変数も参照可能)
END;
-- DBMS_OUTPUT.PUT_LINE(inner_var); -- エラー(内側の変数は外では使えない)
END;
このように、内側のブロックは外側の変数を参照できますが、外側のブロックから内側の変数は参照できません。
変数のスコープ(有効範囲)
変数のスコープは、それが宣言されたブロック内に限定されます。外側のブロックで宣言された変数は内側のブロックでも使用できますが、内側で宣言された変数は外側からは見えません。
また、同じ名前の変数が内側のブロックで再宣言された場合、内側の変数が優先され、外側の変数は隠蔽されます。
DECLARE
message VARCHAR2(50) := '外部';
BEGIN
DBMS_OUTPUT.PUT_LINE('外部ブロック: ' || message); -- 外部
DECLARE
message VARCHAR2(50) := '内部';
BEGIN
DBMS_OUTPUT.PUT_LINE('内部ブロック: ' || message); -- 内部
END;
DBMS_OUTPUT.PUT_LINE('再び外部ブロック: ' || message); -- 外部
END;
このように、変数の名前が被った場合、内側の変数が優先されるため、名前の付け方には注意が必要です。
例外処理のネスト
例外処理もブロック単位でネスト可能です。内側で例外が処理されなければ、外側のEXCEPTIONブロックに伝播します。
BEGIN
BEGIN
RAISE NO_DATA_FOUND;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('内部ブロックで処理: TOO_MANY_ROWS');
-- NO_DATA_FOUNDは処理されないので外部に伝播
END;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('外部ブロックで処理: NO_DATA_FOUND');
END;
このように、内部で処理されない例外は、外部ブロックに伝播してキャッチされるため、階層的な例外制御が可能です。
ネストブロックの活用シーン
ネストブロックは以下のような場面で有効に使えます。
- 一時的な変数を局所的に使用したいとき
- 部分的な処理だけ例外を切り分けて扱いたいとき
- 構造化されたロジックを明確にしたいとき
無闇にネストを深くすると可読性が落ちるため、必要な場面で適切に使うことが大切です。
まとめ
PL/SQLのネストブロックを使えば、処理を論理的に分割し、変数や例外のスコープを制御できます。内側のブロックは外側の変数にアクセスできますが、逆はできません。同じ名前の変数が内外に存在する場合は、内側の変数が優先されます。
スコープの正しい理解は、保守性・再利用性の高いコードを書くうえで重要です。PL/SQLで効率的なコードを書くために、ネストブロックの構造とそのスコープをぜひ習得しておきましょう。