【Oracle】ORA-06532の原因と解決方法|Subscript outside of limit の直し方

【Oracle】ORA-06532の原因と解決方法|Subscript outside of limit の直し方 Oracle

ORA-06532: Subscript outside of limit は、Oracle PL/SQLのコレクションで、添字が許容範囲外になった時に発生するエラーです。代表例は、VARRAY(3) に4件目を追加しようとした場合や、ネスト表・VARRAYで 0 や負の添字を使った場合です。

Oracle公式のORA-06532説明でも、添字がVARRAYの上限を超えた、またはVARRAY/ネスト表で非正の添字を使ったことが原因とされています。そのため、修正では LIMITCOUNT、参照している添字の値をセットで確認します。

先に結論
ORA-06532が出たら、まず 添字 <= 0 になっていないか、次に VARRAYLIMIT を超えていないかを確認します。要素数不足なら ORA-06533、未初期化なら ORA-06531 です。
スポンサーリンク

ORA-06532とは

ORA-06532は、PL/SQLコレクションの添字が、型として許される範囲の外にあることを示します。特にVARRAYは最大要素数を型定義で持っているため、LIMIT を超える操作で発生しやすいです。

状態 起きやすいエラー
未初期化 l_codes t_code_list; のまま使う ORA-06531
初期化済み・要素数不足 COUNT=0l_codes(1) ORA-06533
添字が0以下 l_codes(0)l_codes(-1) ORA-06532
VARRAYの上限超え VARRAY(3)に4件目を追加 ORA-06532

VARRAYのLIMITを超える例

もっとも分かりやすい例は、VARRAYの上限を超えて EXTEND するケースです。VARRAYの最大要素数は型定義で決まり、実行時に自由には増やせません。

ora06532-varray-limit.sql
DECLARE
  TYPE t_code_list IS VARRAY(3) OF VARCHAR2(10);
  l_codes t_code_list := t_code_list('A', 'B', 'C');
BEGIN
  l_codes.EXTEND;
  l_codes(4) := 'D';
END;
/

-- ORA-06532: Subscript outside of limit
-- ORA-06512: at line 5

この場合、COUNT はすでに3、LIMIT も3です。4件目を入れたいなら、型定義の上限を見直すか、VARRAYではなくネスト表を使う設計を検討します。

0以下の添字で出る例

ネスト表やVARRAYの添字は、通常1から始まります。0 や負数を添字にすると、要素数とは関係なくORA-06532になります。

ora06532-nonpositive-subscript.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
BEGIN
  DBMS_OUTPUT.PUT_LINE(l_ids(0));
END;
/

-- ORA-06532: Subscript outside of limit

配列を0始まりで扱う言語からPL/SQLに移ってきた時に起きやすいミスです。ループ開始値が 0 になっていないか確認します。

基本の直し方

まず、実際に使っている添字、COUNTLIMIT をログやデバッグ出力で確認します。VARRAYなら LIMIT を超えないこと、ネスト表なら0以下の添字を使わないことが重要です。

check-count-limit.sql
DECLARE
  TYPE t_code_list IS VARRAY(3) OF VARCHAR2(10);
  l_codes t_code_list := t_code_list('A', 'B', 'C');
BEGIN
  DBMS_OUTPUT.PUT_LINE('COUNT=' || l_codes.COUNT);
  DBMS_OUTPUT.PUT_LINE('LIMIT=' || l_codes.LIMIT);

  IF l_codes.COUNT < l_codes.LIMIT THEN
    l_codes.EXTEND;
    l_codes(l_codes.COUNT) := 'D';
  END IF;
END;
/
症状 確認すること 対処
EXTENDで失敗 COUNTLIMIT に達していないか 上限内なら追加、上限なら型や設計を見直す
l_list(0)で失敗 ループ開始値が0になっていないか 1始まりに直す
負の添字で失敗 添字計算結果が負になっていないか 計算式と入力値を確認する
VARRAYに件数が入りきらない 本当に固定長でよいか 上限拡張またはネスト表へ変更

症状別の最短修正

ORA-06532は、添字そのものが不正なのか、VARRAYの上限に当たっているのかで直し方が変わります。発生行の操作を見て、次のように切り分けます。

症状 原因になりやすい箇所 最短修正
l_list(0)で失敗 0始まりループをPL/SQLに持ち込んでいる ループを1 .. COUNTにする
負の添字で失敗 添字計算やオフセット計算が負になっている 計算結果が1以上かを確認してから参照
EXTENDで失敗 VARRAYがLIMITに達している COUNT < LIMIT の時だけ追加
固定上限のループで失敗 配列件数とループ上限がずれている COUNTLASTから範囲を決める
件数が増えると失敗 VARRAYの上限が業務データに合っていない 上限拡張、ネスト表化、処理分割を検討

ORA-06533との違い

ORA-06532とORA-06533はどちらも添字関連ですが、見る場所が違います。ORA-06533は現在の要素数を超えた参照、ORA-06532は添字が型やルールとして許される範囲外です。

エラー 状態 対処
ORA-06531 コレクションが未初期化 コンストラクタ未実行 ORA-06531を確認
ORA-06533 要素数を超えて参照 COUNT=0l_list(1) ORA-06533を確認
ORA-06532 添字が許容範囲外 VARRAY(3)で4件目、またはl_list(0) LIMITと添字値を確認

PL/SQLコレクションの基礎は PL/SQLコレクション型完全ガイド も合わせて確認すると、ネスト表・VARRAY・連想配列の違いを整理しやすいです。

ループ開始値が0になっている場合

アプリケーション側の配列やJSON配列に合わせて0始まりでループを書いてしまうと、PL/SQLコレクションではORA-06532になります。PL/SQL側では FIRSTLASTCOUNT を使って範囲を決めるのが安全です。

bad-zero-based-loop.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
BEGIN
  FOR i IN 0 .. l_ids.COUNT - 1 LOOP
    DBMS_OUTPUT.PUT_LINE(l_ids(i));
  END LOOP;
END;
/
good-one-based-loop.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
BEGIN
  FOR i IN 1 .. l_ids.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE(l_ids(i));
  END LOOP;
END;
/

添字計算で0や負数になる場合

固定で 0 を書いていなくても、変数計算の結果として0や負数になることがあります。ページ番号、連番、前後行参照、オフセット計算を使う処理では、参照前に添字値を確認します。

bad-calculated-subscript.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
  l_pos PLS_INTEGER := 1;
BEGIN
  DBMS_OUTPUT.PUT_LINE(l_ids(l_pos - 1));
END;
/

-- l_pos - 1 が 0 になるため ORA-06532
good-calculated-subscript.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
  l_pos PLS_INTEGER := 1;
  l_target PLS_INTEGER;
BEGIN
  l_target := l_pos - 1;

  IF l_target BETWEEN 1 AND l_ids.COUNT THEN
    DBMS_OUTPUT.PUT_LINE(l_ids(l_target));
  END IF;
END;
/

BULK COLLECT後に出る場合

BULK COLLECT で取得したコレクションを、別の0始まり添字や固定上限で処理するとORA-06532につながることがあります。取得件数を COUNT で確認し、1始まりで処理します。大量取得の基本は BULK COLLECT / FORALL完全ガイド も参考になります。

bulk-collect-one-based-loop.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list;
BEGIN
  SELECT employee_id
  BULK COLLECT INTO l_ids
  FROM employees
  WHERE department_id = 10;

  FOR i IN 1 .. l_ids.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE(l_ids(i));
  END LOOP;
END;
/

明示的カーソルや BULK COLLECT LIMIT と組み合わせる場合は、明示的カーソル完全ガイド のように取得件数ごとの終了条件を明確にします。

VARRAYの上限を見直す場合

VARRAYは「最大件数が決まっている」ことに意味がある型です。上限を超えるデータが普通に入るなら、単に LIMIT を大きくするだけでなく、ネスト表の方が自然かも検討します。

選択肢 向いているケース 注意点
VARRAYの上限を増やす 最大件数が業務上明確 型変更の影響範囲を確認する
ネスト表へ変える 件数が可変で上限が読みづらい SQL型や保存形式への影響を確認する
処理を分割する 一度に扱う件数を制限したい 順序や重複の扱いを設計する
入力値を制限する 画面やAPIで件数上限を持てる DB側でも防御する

FORALLで出る場合

FORALL で固定範囲を使うと、VARRAYの上限や実在する添字とずれてエラーになることがあります。疎なコレクションや削除済み要素を扱うなら、INDICES OF の利用も検討します。

forall-safe-range.sql
DECLARE
  TYPE t_num_list IS TABLE OF NUMBER;
  l_ids t_num_list := t_num_list(10, 20, 30);
BEGIN
  FORALL i IN INDICES OF l_ids
    INSERT INTO work_ids(id) VALUES (l_ids(i));
END;
/

調査手順

実際にORA-06532が出たら、ORA-06512の行番号から USER_SOURCE で該当行を確認します。その行で使っている添字、ループ開始値、VARRAYの LIMITCOUNT を順番に見ます。

check-user-source-ora06532.sql
SELECT line,
       text
FROM user_source
WHERE name = 'PKG_ORDER'
  AND type = 'PACKAGE BODY'
  AND line BETWEEN 80 AND 100
ORDER BY line;

行番号の読み方は ORA-06512の原因と読み方 を確認してください。

順番 見る場所 確認内容
1 ORA-06512の行番号 どの行で添字を使っているか
2 添字の値 0以下、または想定外に大きくないか
3 COUNT 現在の要素数
4 LIMIT VARRAYの最大件数
5 ループ範囲 0始まりや固定上限になっていないか

よくある原因と対処一覧

原因 症状 対処
0始まりループ l_list(0)で失敗 1始まり、またはFIRST/LASTを使う
VARRAYの上限超え EXTENDや代入で失敗 COUNT < LIMITを確認
添字計算の結果が負 条件によってだけ失敗 入力値と計算式を確認
固定上限で処理 件数が変わると失敗 COUNTLIMITから範囲を決める
型選択が合っていない VARRAYの上限に何度も当たる ネスト表や処理分割を検討

チェックリスト

項目 OKの状態
添字が1以上 0や負数を使っていない
VARRAYのLIMIT内 COUNTLIMIT を超えない
固定値ではなくCOUNTを使った 要素数に応じて範囲が決まる
0件時の処理がある 空コレクションでループや参照をしない
ORA-06512の行を確認した 発生行と呼び出し元を分けている

よくある質問

ORA-06532とORA-06533は何が違いますか?

ORA-06533は現在の要素数を超えた参照、ORA-06532は添字がVARRAYの上限を超える、または0以下など許容範囲外の状態です。

VARRAYのLIMITは実行時に増やせますか?

VARRAYの上限は型定義で決まります。上限を変えるには型や設計の見直しが必要です。

ネスト表でもORA-06532になりますか?

はい。0以下の添字を使うとネスト表でもORA-06532になります。要素数不足ならORA-06533になりやすいです。

JavaScriptやJavaの配列のように0始まりで扱えますか?

通常のPL/SQLコレクションでは1始まりとして扱います。0始まりのループをそのまま移植しないようにします。

まとめ

ORA-06532は、PL/SQLコレクションの添字が許容範囲外になった時に発生します。代表的な原因は、VARRAYの LIMIT を超える操作、または0以下の添字です。

対処は、COUNTLIMIT、実際の添字値を確認し、0始まりループを直す、上限を超える前に分岐する、VARRAYの設計を見直す、という流れです。要素数不足の問題ならORA-06533、未初期化ならORA-06531として切り分けると迷いにくくなります。

参考

ORA-06532 - Oracle Database Error Help

PL/SQL Collections and Records - Oracle Database PL/SQL Language Reference

Collection Methods - Oracle Database PL/SQL Language Reference