ORA-06531: Reference to uninitialized collection は、Oracle PL/SQLで初期化していないコレクションを参照した時に発生するエラーです。特にネスト表やVARRAYを宣言しただけで、コンストラクタを呼ばずに COUNT、EXTEND、要素代入、ループ処理をしようとした時に起きます。
Oracle公式のエラー説明でも、未初期化のコレクションを参照していることが原因で、対象コレクションを初期化してから使う必要があります。PL/SQLのコレクション全体の基本は PL/SQLコレクション型完全ガイド も参考になります。
ネスト表・VARRAYは、宣言しただけでは空ではなく NULL状態のコレクション です。
l_list := t_num_list(); のようにコンストラクタで初期化してから、必要に応じて EXTEND して要素を入れます。初期化済みだが要素数が足りない場合は、ORA-06531ではなく ORA-06533: Subscript beyond count になりやすいです。ORA-06531とは
ORA-06531は、PL/SQLの事前定義例外 COLLECTION_IS_NULL に対応するエラーです。コレクション変数そのものがNULL状態のまま、要素やメソッドに触れた時に発生します。
| 状態 | 意味 | 起きやすいエラー |
|---|---|---|
| 未初期化 | コレクション変数がNULL | ORA-06531 |
| 初期化済み・要素0件 | 空のコレクション | 要素参照でORA-06533になりやすい |
| 初期化済み・要素あり | 通常利用できる状態 | 添字や型の問題がなければOK |
| 連想配列 | コンストラクタを使わないPL/SQLコレクション | ネスト表/VARRAYとは扱いが違う |
発生する典型例
次の例では、ネスト表型の変数を宣言しただけで、コンストラクタを呼んでいません。この状態で EXTEND や要素代入をすると、ORA-06531が発生します。
DECLARE TYPE t_num_list IS TABLE OF NUMBER; l_ids t_num_list; BEGIN l_ids.EXTEND; l_ids(1) := 100; END; / -- ORA-06531: Reference to uninitialized collection -- ORA-06512: at line 5
ここで重要なのは、l_ids は「空の配列」ではなく「NULL状態のコレクション」だという点です。ORA-06512の行番号の読み方は ORA-06512の原因と読み方 で詳しく整理しています。
基本の直し方
ネスト表やVARRAYは、型名と同じコンストラクタを呼んで初期化します。空で始めたい場合でも、空のコンストラクタを代入してから使います。
DECLARE TYPE t_num_list IS TABLE OF NUMBER; l_ids t_num_list := t_num_list(); BEGIN l_ids.EXTEND; l_ids(1) := 100; DBMS_OUTPUT.PUT_LINE(l_ids(1)); END; /
| やりたいこと | 書き方 | 注意点 |
|---|---|---|
| 空で初期化する | l_ids := t_num_list(); |
この時点では要素数0件 |
| 1件追加する | l_ids.EXTEND; |
追加後にl_ids(l_ids.COUNT)へ代入 |
| 初期値付きで作る | t_num_list(10, 20, 30) |
最初から3要素ある |
| 再初期化する | l_ids := t_num_list(); |
既存要素は消える |
症状別の最短修正
ORA-06531は、どこで未初期化になっているかによって直し方が少し変わります。まずは次の表で、該当する症状から確認します。
| 症状 | 原因になりやすい箇所 | 最短修正 |
|---|---|---|
l_list.EXTENDで失敗 |
宣言後にコンストラクタを呼んでいない | l_list := t_list(); を先に実行 |
l_list(1) := ...で失敗 |
未初期化、または要素追加前 | 初期化してからEXTEND |
| 呼び出し元で失敗 | 関数戻り値やOUT引数がNULLコレクション | 0件でも空コレクションを返す |
| オブジェクト属性で失敗 | 親オブジェクト生成時に子コレクションがNULL | 属性にもtype_name()を渡す |
| 修正後にORA-06533になる | 初期化はできたが要素数が足りない | COUNT確認とEXTENDを追加 |
空のコレクションとNULLコレクションの違い
ORA-06531で混乱しやすいのは、空とNULLが違うことです。初期化済みで要素が0件のコレクションは空です。一方、宣言しただけのネスト表やVARRAYはNULL状態です。
DECLARE TYPE t_num_list IS TABLE OF NUMBER; l_null_list t_num_list; l_empty_list t_num_list := t_num_list(); BEGIN -- l_null_list.COUNT は ORA-06531 になり得る DBMS_OUTPUT.PUT_LINE(l_empty_list.COUNT); -- 0 END; /
EXISTS はNULLコレクションにも使える場面がありますが、通常の実装では「使う前に初期化する」方針にした方が読みやすく、安全です。
ORA-06531とORA-06533の違い
ORA-06531と混同しやすいのが ORA-06533: Subscript beyond count です。どちらもコレクションで出ますが、原因は違います。
| エラー | 状態 | 例 | 対処 |
|---|---|---|---|
ORA-06531 |
コレクション自体が未初期化 | l_ids.EXTEND の前にコンストラクタ未実行 |
コンストラクタで初期化する |
ORA-06533 |
初期化済みだが要素数が足りない | l_ids(1) に代入したいがCOUNT=0 |
EXTENDしてから代入する |
ORA-06502 |
要素の型や桁が合わない | 文字列長不足、数値変換エラー | ORA-06502を確認する |
DECLARE TYPE t_num_list IS TABLE OF NUMBER; l_ids t_num_list := t_num_list(); BEGIN l_ids(1) := 100; END; / -- 初期化済みだが要素がないため、ORA-06533になりやすい -- l_ids.EXTEND; を先に実行する
VARRAYの場合
VARRAYも、宣言しただけではNULL状態です。ネスト表と同じく、コンストラクタで初期化してから使います。ただしVARRAYには最大要素数があるため、LIMIT も意識します。
DECLARE TYPE t_code_list IS VARRAY(3) OF VARCHAR2(10); l_codes t_code_list := t_code_list(); BEGIN l_codes.EXTEND; l_codes(1) := 'A001'; DBMS_OUTPUT.PUT_LINE(l_codes.COUNT || '/' || l_codes.LIMIT); END; /
オブジェクト型の属性で起きる場合
実務で多いのが、オブジェクト型の属性としてネスト表を持っているケースです。オブジェクト自体を生成していても、コレクション属性を初期化していないとORA-06531になります。
CREATE TYPE t_num_list AS TABLE OF NUMBER; / CREATE TYPE t_order_obj AS OBJECT ( order_id NUMBER, item_ids t_num_list ); / DECLARE l_order t_order_obj := t_order_obj(1001, NULL); BEGIN l_order.item_ids.EXTEND; END; / -- item_ids がNULLなので ORA-06531
DECLARE l_order t_order_obj := t_order_obj(1001, t_num_list()); BEGIN l_order.item_ids.EXTEND; l_order.item_ids(1) := 501; END; /
BULK COLLECTで扱う場合
BULK COLLECT でコレクションに取得する場合も、後続処理では件数確認が重要です。取得結果が0件なら、ループや要素参照で別のエラーにつながることがあります。大量データ処理は BULK COLLECT / FORALL完全ガイド も参考になります。
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 = -1;
IF l_ids.COUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE(l_ids(1));
END IF;
END;
/
明示的カーソルや BULK COLLECT LIMIT を使う処理では、明示的カーソル完全ガイド も合わせて見ると切り分けやすいです。
初期化漏れを防ぐ書き方
ORA-06531は、宣言場所で初期化する、または初期化関数を通すことでかなり防げます。パッケージ変数、OUT引数、オブジェクト属性では特に初期化漏れが起きやすいです。
DECLARE TYPE t_num_list IS TABLE OF NUMBER; l_ids t_num_list := t_num_list(); BEGIN NULL; END; /
CREATE OR REPLACE PACKAGE pkg_order AS
TYPE t_num_list IS TABLE OF NUMBER;
FUNCTION empty_ids RETURN t_num_list;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg_order AS
FUNCTION empty_ids RETURN t_num_list IS
BEGIN
RETURN t_num_list();
END;
END;
/
OUT引数・関数戻り値でNULLを返す場合
呼び出し先ではエラーにならず、呼び出し元でORA-06531になる場合は、OUT引数や関数戻り値としてNULLコレクションを返している可能性があります。0件を表したい場合でも、NULLではなく空コレクションを返す方が安全です。
CREATE OR REPLACE FUNCTION get_order_ids RETURN pkg_order.t_num_list IS l_ids pkg_order.t_num_list; BEGIN RETURN l_ids; END; / -- 呼び出し元で result.COUNT や result.EXTEND を呼ぶと ORA-06531 になり得る
CREATE OR REPLACE FUNCTION get_order_ids RETURN pkg_order.t_num_list IS l_ids pkg_order.t_num_list := pkg_order.t_num_list(); BEGIN RETURN l_ids; END; / -- 0件でも空コレクションを返す
調査手順
実際の障害対応では、ORA-06531の直後に出る ORA-06512 の行番号から、USER_SOURCE で未初期化の変数を探します。ログに DBMS_UTILITY.FORMAT_ERROR_BACKTRACE を残しておくと、後から行番号を追いやすくなります。
SELECT line,
text
FROM user_source
WHERE name = 'PKG_ORDER'
AND type = 'PACKAGE BODY'
AND line BETWEEN 120 AND 140
ORDER BY line;
| 順番 | 見る場所 | 確認内容 |
|---|---|---|
| 1 | ORA-06512の最初のオブジェクト付き行 | どのプロシージャ、パッケージ、行番号か |
| 2 | 該当行のコレクション変数 | 宣言時または直前で初期化しているか |
| 3 | 代入・引数・戻り値 | NULLコレクションを受け取っていないか |
| 4 | オブジェクト属性 | 属性のネスト表/VARRAYを初期化しているか |
| 5 | 例外ログ | エラー番号とバックトレースが残っているか |
ログ設計は DBMS_UTILITY完全ガイド、例外処理の全体像は PL/SQL例外処理ガイド が参考になります。
よくある原因と対処一覧
| 原因 | 症状 | 対処 |
|---|---|---|
| 宣言しただけで使っている | l_list.EXTENDでORA-06531 |
宣言時に:= type_name(); |
| プロシージャのOUT引数にNULLを返している | 呼び出し元でCOUNTや要素参照時に失敗 | 0件でも空コレクションを返す |
| オブジェクト属性がNULL | obj.items.EXTENDで失敗 |
オブジェクト生成時に属性もコンストラクタで初期化 |
| 初期化と要素追加を混同している | ORA-06531修正後にORA-06533 | EXTEND後に添字代入 |
| 例外を握りつぶしている | 原因行が分からない | バックトレースをログに残してRAISE |
チェックリスト
| 項目 | OKの状態 |
|---|---|
| ネスト表・VARRAYを初期化した | type_name() を代入している |
| 要素代入前にEXTENDした | COUNT が必要な添字以上になっている |
| OUT引数や戻り値でNULLを返していない | 0件なら空コレクションを返している |
| オブジェクト属性も初期化した | 親オブジェクトだけでなく子コレクションも生成済み |
| ORA-06512の行番号を確認した | 発生行と呼び出し元を分けて読んでいる |
よくある質問
宣言しただけでは空のコレクションになりませんか?
ネスト表やVARRAYは、宣言しただけではNULL状態です。空にしたい場合でも、コンストラクタで初期化します。
EXTENDしているのにORA-06531になります
EXTEND 自体をNULLコレクションに対して呼んでいる可能性があります。先に l_list := t_list(); のように初期化します。
ORA-06531とORA-06533はどちらを見ればよいですか?
未初期化ならORA-06531、初期化済みだが要素数不足ならORA-06533です。まずコンストラクタ、その次にEXTENDの有無を確認します。
連想配列でもコンストラクタが必要ですか?
連想配列はネスト表やVARRAYと違い、コンストラクタを使いません。この記事の主な対象は、コンストラクタで初期化するネスト表とVARRAYです。
まとめ
ORA-06531は、未初期化のPL/SQLコレクションを参照した時に発生するエラーです。ネスト表やVARRAYは、宣言しただけでは空ではなくNULL状態なので、type_name() で初期化してから EXTEND や要素代入を行います。
ORA-06531を直した後に添字エラーが出る場合は、初期化はできていても要素数が足りない可能性があります。ORA-06512の行番号を見ながら、コンストラクタ、EXTEND、COUNT確認、例外ログの順に確認するのが近道です。
参考
ORA-06531 – Oracle Database Error Help
PL/SQL Collections and Records – Oracle Database PL/SQL Language Reference
Collection Method Invocation – Oracle Database PL/SQL Language Reference
