SQL

ORA-06502の直し方|エラー文から原因を見分ける診断手順とPL/SQL対策

k.w
\お買い物マラソン開催中/
Contents
  1. ORA-06502が出たら最初に確認すること
  2. ORA-06502の本質と関連エラーの違い
  3. エラー詳細から原因候補を絞り込む
  4. ORA-06512から発生行を特定する診断手順
  5. 原因に合わせて修正方法を選ぶ
  6. 動的SQL・カーソル・コレクションを調べる
  7. Rails・Java・Pythonから呼ぶ場合の確認ポイント
  8. 例外処理で原因を隠さず安全に記録する
  9. 再発防止・原因別早見表・FAQ
スポンサーリンク

ORA-06502が出たら最初に確認すること

ORA-06502が発生したときは、すぐに変数サイズを広げたり例外処理を追加したりするのではなく、エラー全文と発生行を残してから原因を絞り込みます。

ORA-06502は複数の原因で発生するため、エラー番号だけを見て修正方法を決めると、別の不具合を見逃す可能性があります。

最初に客観的な情報をそろえておけば、文字列変換、長さ不足、NULL、数値精度、バインド不整合などの候補を効率よく切り分けられます。

エラーメッセージを省略せず保存する

最初に保存するのは、ORA-06502の番号だけではなく、その後ろに続く詳細メッセージを含むエラー全文です。

詳細メッセージには、文字列から数値への変換失敗、文字列バッファ不足、NULL代入、数値精度超過など、原因を絞り込むための情報が含まれることがあります。

画面やログに一部しか表示されていない場合は、アプリケーション側の例外オブジェクトやデータベース側のログも確認します。

フレームワークが例外メッセージを短縮している場合は、原因例外やスタックトレースを取得できる設定がないか確認します。

エラー文を短く切って記録すると、原因の分類に必要な情報が失われるため、改行を含めた状態で保存することが大切です。

同じ処理で複数のORA番号が表示されている場合は、ORA-06502だけを抜き出さず、前後を含めて一つのエラースタックとして残します。

発生日時、処理名、対象ユーザー、ジョブID、リクエストIDなども添えておくと、アプリケーション側のログと照合しやすくなります。

ただし、入力値に個人情報や認証情報が含まれる場合は、値をそのまま保存せず、必要な部分だけをマスクします。

ORA-06512の行番号を確認する

ORA-06512は原因そのものではなく、例外が発生したPL/SQLブロック、パッケージ、プロシージャ、行番号を示す情報です。

ORA-06502が「何が起きたか」を示す情報であるのに対し、ORA-06512は「どこで起きたか」を調べるための手掛かりです。

複数のORA-06512が並ぶ場合は、先頭に近い行から確認し、最初に例外が発生した場所と、その処理を呼び出した場所を分けて考えます。

後ろに並ぶORA-06512は、呼び出し元のプロシージャ、トリガー、匿名ブロックなどを示していることがあります。

最初に発生した行を特定できたら、その行だけでなく、直前に値を作っている処理も確認します。

エラーが代入時に表面化していても、問題のある値は数行前のSELECT文や関数呼び出しで作られている場合があります。

行番号がソースと合わない場合は、実行中のオブジェクトが最新コンパイル版か、参照しているスキーマが正しいかも確認します。

パッケージを修正した後に再コンパイルしていない場合や、同名オブジェクトが別スキーマに存在する場合は、表示された行番号と手元のソースがずれることがあります。

修正前の値・型・長さ・NULLを記録する

原因調査では、修正前の入力値、変数のデータ型、宣言サイズ、NULLの有無を記録しておくことが重要です。

代入元の値だけでなく、代入先の宣言も並べて残すと、値の問題か受け取り側の問題かを判断しやすくなります。

文字列では実際の値に加えて、文字数、バイト数、先頭と末尾の空白、改行や制御文字の有無を確認します。

数値では整数部と小数部の桁数、符号、指数表記、桁区切り記号、小数点記号を確認します。

NULLに見える値が空文字や空白だけの文字列である場合もあるため、NULL判定と文字列内容の確認は分けて行います。

動的SQLや外部アプリケーションから値を受け取る処理では、バインド時に指定された型とPL/SQL側の引数型も記録します。

本番環境で再現しにくい場合は、個人情報や機密情報を伏せたうえで、同じ条件を作れる範囲の情報を保存します。

値そのものを残せない場合でも、文字数、バイト数、数値桁数、NULLの有無、形式の特徴を残せば、原因調査に利用できます。

修正前の状態を残さずに変数サイズや変換処理を変更すると、エラーは消えても本当の原因を確認できなくなることがあります。

5分で行う初動チェック

最初の5分では、エラー全文、ORA-06512の行番号、該当行の代入元と代入先、実際の値、型、長さ、NULLを順番に確認します。

まず、エラーメッセージが途中で切れていないかを確認します。

次に、最初のORA-06512が示すオブジェクトと行番号を開きます。

該当行で代入、変換、演算、FETCH、プロシージャ呼び出しのどれが行われているかを確認します。

代入処理であれば、右辺の値と左辺の宣言を並べて比較します。

文字列ならLENGTHとLENGTHBを確認し、数値なら精度とスケールに収まるかを確認します。

NOT NULL変数や制約付きサブタイプがある場合は、NULLが渡されていないかを確認します。

動的SQLや外部アプリケーションからの呼び出しでは、バインド変数の型、順番、INとOUTの方向も確認します。

この段階では原因を決めつけず、観測できた情報をそろえてから、詳細メッセージに対応する原因候補へ進みます。

初動チェックで原因を特定できない場合でも、確認済みの項目を記録しておけば、同じ調査を繰り返さずに済みます。

ORA-06502の本質と関連エラーの違い

ORA-06502はPL/SQLで扱う値が宣言や処理の条件に合わないときに発生するため、変換、長さ、NULL、桁数などを広く確認する必要があります。

同じエラー番号でも、発生したコードと詳細メッセージによって、確認すべき場所や修正方法は異なります。

ORA-01722やORA-06512と同時に見かけることもあるため、それぞれの役割を分けて理解することが重要です。

PL/SQLのVALUE_ERRORとは

PL/SQLではORA-06502が事前定義例外のVALUE_ERRORとして扱われます。

VALUE_ERRORは、文字列を数値へ変換できない場合、短い変数へ長い文字列を代入した場合、制約に合わない値を入れた場合などに発生します。

数値の計算結果が変数の精度を超えた場合や、NOT NULLとして宣言された変数へNULLを代入した場合にも発生する可能性があります。

プロシージャの引数、関数の戻り値、カーソルのFETCH先、動的SQLのINTO先でも、値と宣言が合わなければ同様の問題が起こります。

同じORA-06502でも原因は一つではないため、例外名だけで修正方法を決めず、詳細メッセージと発生行を組み合わせて判断します。

VALUE_ERRORを例外処理で捕捉できたとしても、原因が解消されたわけではありません。

例外処理では、発生場所と入力値を記録し、必要に応じて呼び出し元へエラーを返す設計が必要です。

4種類の代表的な詳細メッセージ

実務では、character to number conversion error、character string buffer too small、null value not allowed、number precision too largeが代表的な手掛かりになります。

character to number conversion errorは、数値へ変換できない文字列や、想定と異なる形式の値が渡された可能性を示します。

character string buffer too smallは、文字列を受け取る変数やOUTパラメータのサイズが不足している可能性を示します。

null value not allowedは、NULLを許可しない変数やサブタイプへNULLが代入された可能性を示します。

number precision too largeは、数値の桁数が宣言した精度やスケールに収まらない可能性を示します。

この4種類は原因を整理するための代表例であり、ORA-06502が必ず4種類だけに限定されるという意味ではありません。

環境や処理内容によって表示が異なることもあるため、詳細メッセージが見つからない場合は、発生行の代入や変換を一つずつ調べます。

表示された英文を日本語へ意訳するときは、元の詳細メッセージも残しておくと、検索やチーム内共有に利用しやすくなります。

ORA-06502とORA-01722の違い

ORA-06502はPL/SQL内の代入や演算などで値が合わないときに発生し、PL/SQLではVALUE_ERRORとして捕捉できます。

ORA-01722はSQL文の評価中に数値へ変換できない値が見つかったときに発生し、PL/SQLではINVALID_NUMBERとして扱われます。

SQL文のWHERE句やJOIN条件で暗黙変換が起きている場合はORA-01722を疑い、PL/SQL変数への代入や関数内の変換ではORA-06502を疑います。

ただし、SQLとPL/SQLが連続して実行される処理では、どちらの段階で変換が行われたかをコードから確認する必要があります。

たとえば、文字列列と数値列を比較するSQLでは、SQL評価中の暗黙変換が原因になりやすくなります。

一方で、SELECT結果をNUMBER型変数へ受け取る際に変換が起きる場合は、PL/SQL側でORA-06502として表面化することがあります。

エラー番号だけでなく、発生した文がSQL文なのかPL/SQL代入なのかを確認すると、調査範囲を絞りやすくなります。

ORA-06512は原因ではなく発生位置情報

ORA-06512は、エラースタックの中で例外が発生した場所や呼び出し経路を示します。

ORA-06512だけを見ても、変換失敗、文字列長、NULL、数値精度のどれが原因かは判断できません。

原因を示すORA-06502の詳細メッセージと、場所を示すORA-06512の行番号をセットで読むことが診断の基本です。

複数のORA-06512が表示される場合は、例外が発生した場所から外側の呼び出し元へ向かってスタックが並びます。

最初の行だけで判断せず、呼び出し経路全体を見ると、問題の値がどこから渡されたかを追跡できます。

トリガーや共通パッケージを経由している場合は、利用者が直接実行したSQLとは別の場所でORA-06502が発生することもあります。

ORA-06512をエラー原因として修正しようとするのではなく、示された行にある代入や変換を調べることが重要です。

エラー詳細から原因候補を絞り込む

ORA-06502の後ろに表示される詳細メッセージを確認すると、最初に調べる値や変数を効率よく絞り込めます。

詳細メッセージがある場合は、すべての原因を同時に疑うのではなく、該当する処理から優先して確認します。

ただし、表示内容だけで原因を断定せず、発生行と実際の値で裏付けを取る必要があります。

character to number conversion error

この詳細は、数値へ変換できない文字列をNUMBER型の変数へ代入した場合や、TO_NUMBERへ不正な文字列を渡した場合に現れます。

空文字、空白、英字、通貨記号、単位、全角数字、想定外の小数点記号が含まれていないかを確認します。

見た目が数値でも、先頭や末尾に空白や制御文字が含まれていると、変換に失敗することがあります。

小数点や桁区切りの解釈はNLS設定の影響を受けるため、本番環境だけで発生する場合はNLS_NUMERIC_CHARACTERSも比較します。

アプリケーション側では文字列として扱われていても、PL/SQL引数がNUMBER型であれば、呼び出し時に暗黙変換が行われる可能性があります。

CSVや外部ファイルから読み込んだ値では、ヘッダー行、空欄、引用符、改行コードが混入していないかも確認します。

解決時は無条件に変換するのではなく、入力形式を検証し、想定外の値をエラーとして扱うかを決めます。

変換できない値を0へ置き換える処理は、0が業務上有効な値である場合に原因を隠す可能性があります。

数値変換の前に入力値を記録し、どの形式を許可するかを明確にすると再発防止につながります。

character string buffer too small

この詳細は、代入する文字列が受け取り側の変数やOUTパラメータより長い場合に発生します。

VARCHAR2変数だけでなく、固定長のCHAR、関数の戻り値、カーソルのFETCH先、外部アプリケーション側の受信バッファも確認します。

CHARは固定長として扱われるため、空白埋めによって想定より長い値になることがあります。

文字列連結を行っている場合は、個々の値が短くても、連結後の結果が宣言サイズを超えることがあります。

日本語を含むデータでは文字数とバイト数が一致しないことがあるため、LENGTHとLENGTHBを両方確認します。

絵文字や一部の記号は、環境によって複数バイトで扱われるため、英数字だけのテストでは問題が再現しないことがあります。

OUTパラメータでは、PL/SQL側の宣言が十分でも、呼び出し元ドライバが確保した受信サイズが小さい場合があります。

受け取り側を広げる修正は有効ですが、想定外に長い値を許可してよいかを業務要件と合わせて判断します。

本来は入力エラーとして拒否すべき値を、サイズ拡大だけで受け入れると、後続の画面やファイル出力で別の問題が起こる可能性があります。

null value not allowed

この詳細は、NOT NULL制約を持つ変数やサブタイプへNULLを代入した場合に発生します。

入力引数がNULLの場合だけでなく、SELECT結果、関数の戻り値、条件分岐の未設定、外部結合の結果などからNULLが発生することがあります。

変数に初期値が設定されていても、後続処理でNULLを代入すればエラーになります。

条件分岐の一部でしか値を設定していない場合は、特定のデータだけでNULLが残ることがあります。

NVLやCOALESCEで既定値へ置き換える方法はありますが、欠損を隠してよい項目かを確認してから使います。

金額のNULLを0へ変換すると、未入力と実際の0を区別できなくなる場合があります。

日付のNULLを現在日時へ変換すると、本来の入力日時として誤って扱われる可能性があります。

必須値であるなら、代入直前ではなく入力境界でNULLを検出し、利用者や呼び出し元へ分かる形で返す方が安全です。

NULLがどこで発生したかを追跡するため、値を作成する関数やSELECT文まで遡って確認します。

number precision too large

この詳細は、NUMBER型の精度やスケールに収まらない値を代入した場合に発生します。

整数部の桁数が多すぎる場合だけでなく、小数部を含めた全体の精度が宣言を超える場合にも注意が必要です。

計算前の値が範囲内でも、乗算、加算、集計、税率計算などの結果が範囲を超えることがあります。

小数を丸める処理がない場合は、中間計算で想定以上の小数桁が発生することもあります。

変数の精度を広げるだけでなく、入力値が仕様上正しいか、丸めや切り捨てを許可できるかも確認します。

テーブル列へ保存する処理では、PL/SQL変数が値を保持できても、保存先列の精度で失敗する可能性があります。

外部アプリケーション側の数値型がデータベース側より広い場合は、バインド時に初めて問題が表面化することがあります。

金額や件数では自動的な丸めが業務結果へ影響するため、修正前に桁数のルールを明確にします。

異常に大きな値が入力された原因が単位の違いや重複計算である場合は、精度を広げるだけでは根本解決になりません。

詳細メッセージが表示されない場合

詳細が省略されている場合は、ORA-06512の発生行を起点に、その行で行われる代入、変換、演算、関数呼び出しを分解します。

該当行に複数の処理が含まれる場合は、一時変数へ分けて各段階の値を記録すると、失敗した箇所を特定しやすくなります。

関数呼び出しを含む代入文では、関数内部で発生したORA-06502が呼び出し側の行番号として見えることもあります。

動的SQLの場合は、実行されたSQL文字列とバインド値を保存し、静的SQLとして再現できる形にします。

エラー処理でSQLERRMだけを短く保存している場合は、バックトレースも記録するようにログ設計を見直します。

アプリケーションが独自メッセージへ置き換えている場合は、元のデータベース例外を原因例外として保持できないか確認します。

詳細メッセージを取得できない状況でも、代入元と代入先を比較すれば、長さ、型、NULL、精度の候補を順番に除外できます。

ORA-06512から発生行を特定する診断手順

原因がすぐに分からない場合は、ORA-06512の行番号から該当コードを開き、代入元と代入先を順番に比較します。

行番号を確認するだけでなく、その値がどこで作られ、どの経路で渡されたかを追跡することが重要です。

複雑な処理では、一度に全体を理解しようとせず、エラーが発生した一行を小さな処理へ分解します。

複数のORA-06512を上から確認する

複数のORA-06512が並ぶときは、最初に表示される行が例外の発生地点で、後続の行が呼び出し経路を示すことが一般的です。

パッケージ本体、トリガー、匿名ブロック、アプリケーション呼び出しの順に経路をたどると、どこで値が変化したかを追いやすくなります。

たとえば、画面から実行した更新処理であっても、実際のエラーは更新トリガー内の文字列代入で発生している場合があります。

共通関数が複数の処理から呼ばれている場合は、どの呼び出し元から渡された値なのかを区別します。

スタックの途中に同じパッケージが複数回現れる場合は、再帰呼び出しやネストした共通処理も疑います。

同名オブジェクトが複数スキーマにある場合は、所有者名を含めて確認します。

シノニムやデータベースリンクを使用している場合は、手元で確認しているソースと実際の実行先が一致しているかを確認します。

ORA-06512の最後の行だけを見ると、単なる呼び出し元を原因箇所と誤認する可能性があります。

該当行の代入元と代入先を洗い出す

該当行が代入文なら、右辺が代入元で左辺が代入先です。

右辺が関数呼び出しの場合は、関数の戻り値型と実際の戻り値を確認します。

SELECT INTOではSELECTリストとINTO句の変数を位置ごとに並べ、列数、順番、型、長さを比較します。

FETCH文でも、カーソルが返す列と受け取り変数は位置で対応するため、一つずつ照合します。

プロシージャ呼び出しでは、実引数と仮引数の型、方向、桁数、NULL可否を比較します。

一つの式に連結、変換、計算が混在している場合は、一時変数へ分けると失敗した処理を切り分けやすくなります。

暗黙変換が疑われる場合は、TO_CHARやTO_NUMBERなどの明示変換へ分け、どの段階で失敗するかを確認します。

代入先が%TYPEで宣言されていても、右辺が列そのものではなく加工結果であれば、サイズが一致するとは限りません。

値・型・LENGTH・LENGTHB・NULLを出力する

文字列では値そのものに加えて、LENGTH、LENGTHB、先頭と末尾の空白を確認します。

空白や改行が見えにくい場合は、区切り文字で囲んでログへ出すと判別しやすくなります。

NULLは文字列の’NULL’とは異なるため、CASE式などでNULLかどうかを明示してログへ出します。

数値では、文字列として渡された値なのか、すでに数値型として渡された値なのかを区別します。

小数点や桁区切りを含む文字列では、セッションのNLS設定も記録します。

日付や時刻を経由した文字列変換がある場合は、日付書式やタイムゾーンの設定も確認します。

ログへ機密情報をそのまま残せない場合は、値をマスクしつつ、長さ、型、NULL、形式だけを記録します。

巨大な文字列をすべてログへ出すとログ容量を圧迫するため、先頭と末尾の一部、全体長、ハッシュ値などを残す方法もあります。

例外発生後に変数の値が変更される処理では、代入直前にログを出さなければ正しい状態を確認できません。

最小構成のPL/SQLブロックで再現する

本番処理をそのまま複製するのではなく、問題の代入、変換、FETCH、バインドだけを残した小さなブロックを作ります。

入力値を固定し、宣言と一つの処理だけを残すと、エラーがデータ依存か環境依存かを判断しやすくなります。

最小構成で再現できれば、変数宣言、変換式、入力値のどれを変更すると解消するかを安全に比較できます。

修正案ごとに再現ブロックを実行し、正常系だけでなく境界値や異常値も確認します。

元の処理にトリガーや共通関数が含まれる場合は、それらを一つずつ追加しながら再現条件を絞ります。

再現できない場合は、本番と検証環境のNLS設定、文字コード、ドライバ、データ量、コンパイル済みオブジェクトを比較します。

実データを使用できない場合は、文字数、バイト数、桁数、NULL条件だけを再現した匿名化データを用意します。

最小構成を障害記録へ残しておくと、将来の回帰テストや同種エラーの調査にも利用できます。

原因に合わせて修正方法を選ぶ

ORA-06502の修正は、原因となる値を正す方法と、受け取り側の宣言や処理を正す方法を分けて考えると判断しやすくなります。

エラーが消えることだけを目標にせず、入力値を受け入れてよいか、データを欠損させないか、後続処理へ影響しないかを確認します。

同じ詳細メッセージでも、業務ルールによって適切な修正方法は異なります。

文字列から数値への変換を明示する

文字列を数値として扱う必要がある場合は、入力形式を確認してから明示的に変換します。

変換対象に空白や桁区切りが含まれる場合は、許可する形式を明確にします。

複数の数値形式を無条件に受け入れると、同じ文字列が環境によって異なる値として解釈される可能性があります。

変換できない値を0へ置き換えると不正データを見逃すため、業務上の既定値として0が正しい場合に限って使用します。

入力ミスを検出すべき場面では、変換失敗を利用者へ返し、値の修正を求める方が適切です。

外部入力では、データベースへ渡す前とPL/SQLで受け取った後の両方で検証すると原因を追いやすくなります。

アプリケーション側で数値型へ変換してから渡せば、データベース側の暗黙変換を減らせます。

ただし、アプリケーション側とデータベース側で許可する桁数や小数形式が異なると、別の不整合が起こるため仕様をそろえます。

文字列サイズとBYTE・CHARを見直す

文字列バッファ不足では、代入先のVARCHAR2やOUTパラメータが実際の値を収容できるかを確認します。

単純な代入だけでなく、文字列連結、置換、日付の文字列化、JSON生成などで長さが増えていないかを確認します。

BYTE指定ではマルチバイト文字によって収容できる文字数が変わるため、日本語を扱う場合は文字数とバイト数を区別します。

CHAR指定であっても、外部アプリケーションやファイル出力側がバイト数で上限を持つ場合があります。

固定長CHARでは空白埋めが発生するため、比較や連結の前後で想定より長い値になる可能性があります。

サイズを広げる修正では、後続のAPI、画面、ファイル出力にも同じ上限があるかを確認します。

テーブル列、PL/SQL変数、OUTパラメータ、アプリケーション側バッファのうち、一つだけ広げても問題が移動する場合があります。

値を切り詰める場合は、切り捨てられる部分が不要であることを確認し、データ欠損を記録できるようにします。

NUMBERの精度とスケールを合わせる

数値精度の問題では、代入先のNUMBER定義と実際の値の桁数を比較します。

NUMBERの精度は全体の有効桁数であり、スケールは小数点以下の桁数に関係します。

入力値だけでなく、計算途中の結果が宣言範囲を超えていないかも確認します。

丸める場合はROUND、切り捨てる場合はTRUNCなど、業務ルールに合う処理を明示します。

暗黙の丸めや型変換へ依存すると、環境や処理位置によって結果が変わる可能性があります。

変数だけを広げてもテーブル列や外部APIの上限で再び失敗する可能性があるため、データの流れ全体を確認します。

金額では通貨単位と小数桁、数量では最大件数、割合では想定範囲を明確にします。

異常値をそのまま保持できるように精度を広げるのではなく、値が異常になった原因も確認します。

NOT NULLへの代入ルールを見直す

NOT NULL変数へNULLが入る場合は、NULLが発生した処理を特定します。

入力値がNULLなのか、SELECT結果が見つからないのか、条件分岐で値が設定されなかったのかを分けて確認します。

外部結合や集計関数の結果では、想定していなかったNULLが返ることがあります。

既定値を設定する場合は、空文字、0、現在日時などが本当に正しい代替値かを業務要件で判断します。

必須入力の欠落なら、処理を続けるよりも、入力エラーとして早い段階で返す方がデータの整合性を保ちやすくなります。

NULLを許容する設計へ変更する場合は、後続処理がNULLを扱えるかも確認します。

NOT NULL制約を外すだけでは、別の場所でNULLによる計算結果や表示崩れが発生する可能性があります。

NULLが正常状態を表すのか、未入力や処理失敗を表すのかを明確にすると、適切な修正を選びやすくなります。

動的SQL・カーソル・コレクションを調べる

静的な代入に問題が見つからない場合は、実行時に型や並び順が決まる動的SQL、カーソル、コレクションを確認します。

これらの処理はコンパイル時に検出できない不整合が残りやすいため、実行されたSQLと実際のバインド値を確認する必要があります。

変更前後で列順や引数定義が変わっていないかも重要な確認項目です。

EXECUTE IMMEDIATEのUSINGとINTOを確認する

EXECUTE IMMEDIATEでは、USING句へ渡す値の順番と型がSQL内のプレースホルダーに合っているかを確認します。

プレースホルダー名が同じように見えても、実際の対応が出現順に依存するケースでは、順番のずれに注意します。

IN、OUT、IN OUTの方向が異なると、受け取り側へ想定外の値が設定される可能性があります。

INTO句がある場合は、SELECT結果の列数、順番、型、長さと受け取り変数を比較します。

SELECTリストへ列を追加した後にINTO句を変更していない場合は、位置ずれによる型不一致が起こります。

動的SQL文字列とバインド値を別々に記録すると、文字列連結による問題と型不一致を切り分けやすくなります。

SQL文字列へ値を直接連結する方法は、暗黙変換や引用符の問題だけでなく、セキュリティ上の危険もあるため避けます。

同じ動的SQLを固定値で静的SQLとして実行し、結果の型と長さを確認すると原因を絞り込みやすくなります。

REF CURSORのFETCH先を確認する

REF CURSORでは、カーソルが返す列とFETCH先の変数が位置で対応します。

列の順番を変更したのにFETCH先を変更していない場合や、文字列列を数値変数で受けている場合はORA-06502の原因になります。

SELECTリストに式や関数を追加した場合は、元の列と戻り値型が異なる可能性があります。

文字列連結やCASE式では、戻り値の最大長が想定より大きくなる場合があります。

共通のREF CURSORを複数の呼び出し元で使用している場合は、すべてのFETCH先が新しい列構成に対応しているか確認します。

型が頻繁に変わる処理では、戻り値の仕様を文書化し、変更時に呼び出し元を確認できるようにします。

列名だけを見て対応させず、列数、順番、データ型、最大長を一覧にして比較すると安全です。

SELECT INTOの戻り値型を確認する

SELECT INTOでは、列型とPL/SQL変数の型が異なると暗黙変換が発生することがあります。

文字列関数や集計関数を使った結果は元の列と型や長さが変わることがあるため、式全体の戻り値を確認します。

TO_CHARで数値や日付を文字列化した結果は、書式モデルによって長さが変わります。

CASE式の各分岐で異なる型や長さの値を返している場合は、最終的な戻り値型を確認します。

列定義を参照する宣言を使っていても、関数や連結を加えた結果までは自動的に合わせられない点に注意します。

SELECTリストとINTO句が長い場合は、一行ずつ対応表を作ると位置ずれを見つけやすくなります。

ビューやシノニムの定義変更によって戻り値型が変わっていないかも確認します。

コレクションのNULLインデックスを確認する

連想配列では、要素の値だけでなくインデックスとして使うキーも確認します。

キーを作る変数がNULLになると、値の代入前にエラーが発生する可能性があります。

文字列キーでは、空白や大文字小文字の違いによって、想定とは別の要素として扱われることがあります。

初期化していないコレクションや存在しない要素へのアクセスは別の例外になることもあるため、ORA番号をまとめて一つの原因にしないようにします。

FIRST、LAST、NEXTなどで要素を走査する場合は、空のコレクションと疎なインデックスを考慮します。

連番を前提にループすると、削除済みの要素や欠番で別の例外が発生することがあります。

コレクションへ格納する値の型や長さも確認し、キーの問題と要素値の問題を分けて調査します。

Rails・Java・Pythonから呼ぶ場合の確認ポイント

外部アプリケーションからPL/SQLを呼ぶ場合は、データベース内部だけでなく、ドライバが設定したバインド型とサイズを確認します。

アプリケーションの変数型とデータベースの引数型が似ていても、数値精度、文字コード、NULLの扱い、OUTバッファの確保方法が異なる場合があります。

データベース側だけを修正する前に、実際にどの型と値が送信されたかを確認します。

プロシージャの引数定義を確認する

最初に、対象プロシージャやファンクションの引数名、データ型、INとOUTの方向、桁数を確認します。

引数の順番で呼び出している場合は、プロシージャ側の定義変更によって位置がずれていないかを確認します。

名前付き引数を使用している場合でも、アプリケーションライブラリがどのようにバインドするかを確認します。

アプリ側の呼び出しコードが古い仕様のまま残っていると、データベース側を変更した後に型不一致が起こります。

複数バージョンのアプリケーションが同じデータベースを使用している場合は、古い呼び出し仕様が残っていないか確認します。

スキーマやシノニム経由で呼んでいる場合は、実際に到達するオブジェクトを特定します。

パッケージのオーバーロードがある場合は、どのシグネチャが選択されているかも確認します。

ドライバ側のバインド型を合わせる

Rails、JDBC、Pythonのoracledbでは、同じ値でも文字列、整数、小数として渡す方法が異なります。

数値引数へ文字列を渡すと暗黙変換に依存するため、アプリ側で正しい数値型へ変換してからバインドします。

小数を浮動小数点型で渡す場合は、精度の違いが業務計算へ影響しないかを確認します。

NULLを渡すときに型情報が決まらないドライバでは、期待するデータ型を明示する必要があります。

OUTパラメータでは、アプリケーション側が確保する文字列サイズや数値型が十分かを確認します。

PL/SQL側のVARCHAR2サイズを広げても、ドライバ側のOUTバッファが小さいままではエラーが解消しない場合があります。

文字コード変換を伴う接続では、アプリケーション上の文字数とデータベースへ送信されるバイト数が異なる可能性があります。

ドライバやORMのバージョン変更後に発生した場合は、バインド型の推論方法が変わっていないかを確認します。

アプリ側とデータベース側のログを対応させる

アプリ側のリクエストとデータベース側のエラーを対応させるため、共通の処理IDやジョブIDを記録します。

同じ時刻に複数の処理が動く環境では、時刻とユーザー名だけでは正しいログを結び付けられない場合があります。

ログには入力値を無制限に残さず、機密性を考慮しながら型、長さ、NULL、形式、識別情報を保存します。

数値では桁数、文字列では文字数とバイト数、OUTパラメータでは確保サイズを残します。

データベース側ではエラー番号、メッセージ、バックトレース、対象処理IDを記録します。

アプリケーション側では、呼び出したプロシージャ名、引数名、バインド型、ドライバのバージョンを残します。

両側のログを同じ処理IDで検索できれば、どの入力がどのORA-06502につながったかを追跡しやすくなります。

本番環境だけで発生する差を確認する

本番だけでORA-06502が発生する場合は、コード差だけでなく実データと環境設定の差を確認します。

本番ではテスト環境より長い文字列、大きな数値、NULL、特殊文字が保存されている可能性があります。

NLS設定、文字コード、ドライバのバージョン、接続設定、データベースのオブジェクト版を比較します。

接続ユーザーごとにNLS設定が異なる場合は、同じSQLでも数値変換の結果が変わる可能性があります。

アプリケーションサーバーが複数台ある場合は、一部のサーバーだけドライバや設定が異なっていないか確認します。

バッチ処理では、一部のレコードだけが境界値を超えている可能性があるため、失敗したデータの特徴を整理します。

本番データをそのまま複製できない場合は、長さ、形式、桁数、NULL条件を再現した匿名化データを使います。

環境差を確認するときは、一度に複数の設定を変更せず、一つずつ条件をそろえて再現性を確認します。

例外処理で原因を隠さず安全に記録する

例外処理はエラーを消すためではなく、必要な情報を残し、呼び出し元へ適切に失敗を伝えるために使います。

ORA-06502を捕捉して処理を続行する場合は、データの整合性と後続処理への影響を慎重に判断します。

調査情報を残さない例外処理は、一時的に画面上のエラーを減らしても、障害対応を難しくします。

VALUE_ERRORとINVALID_NUMBERを使い分ける

PL/SQL内の値エラーであるORA-06502はVALUE_ERRORで捕捉します。

SQL評価中の無効な数値変換であるORA-01722はINVALID_NUMBERで捕捉します。

発生する例外を区別して捕捉すると、利用者向けメッセージやログ内容を原因に合わせて変更できます。

VALUE_ERRORでは代入先の型や長さを記録し、INVALID_NUMBERではSQL文と変換対象の値を記録すると調査しやすくなります。

特定の例外で捕捉できない場合に備えてOTHERSを置くことはできますが、先に具体的な例外を記述します。

OTHERSだけで処理すると、ORA-06502以外の障害も同じ扱いになり、原因ごとの対応が難しくなります。

例外名だけでなくSQLCODEも記録しておけば、想定した例外が実際に発生したかを確認できます。

WHEN OTHERSで握りつぶさない

WHEN OTHERSで何もせず処理を続けると、失敗したデータが成功扱いになり、後から原因を追えなくなります。

バッチ処理では一件の失敗を無視した結果、集計件数や更新件数が合わなくなる可能性があります。

トランザクション途中の例外を握りつぶすと、一部の処理だけが完了した状態になることもあります。

例外を捕捉したら、必要な情報を記録し、処理を中止するか、呼び出し元へ再送出するかを決めます。

処理を継続する設計では、失敗したデータを別テーブルへ記録し、後から再処理できる仕組みを用意します。

利用者向けのメッセージと内部調査用ログを分けると、機密情報を守りながら調査可能性を保てます。

利用者には入力項目や再操作方法を示し、内部ログにはエラー番号、発生行、値の状態を残します。

例外を別のエラーへ置き換える場合も、元のORA番号とバックトレースを失わないようにします。

バックトレースと入力値を記録する

ログにはSQLCODE、SQLERRM、バックトレース、処理名、主要な入力値の状態を一組で残します。

エラー番号だけでは原因を区別できず、メッセージだけでは発生位置を追えないため、両方を記録します。

バックトレースを残すと、例外処理を経由した後でも元の発生行を確認しやすくなります。

入力値は必要最小限とし、個人情報、認証情報、機密データをそのまま保存しないようにします。

文字列なら長さとバイト数、数値なら桁数、共通項目としてNULLの有無を記録すると切り分けに役立ちます。

動的SQLではSQL文字列、バインド名、型、値の形式を残します。

外部アプリケーションからの呼び出しでは、処理ID、接続ユーザー、ドライバ、引数の方向も残します。

ログ出力自体で別の例外が発生しないように、巨大な値やNULLを安全に扱える形式にします。

場当たり的な修正のデメリット

VARCHAR2を無条件に広げると、想定外の長いデータを後続処理へ流す可能性があります。

後続のテーブル列やAPIに同じ長さを保存できなければ、エラーが別の場所へ移動するだけです。

SUBSTRで常に切り詰めると、エラーは消えても必要な文字が失われ、データ欠損に気づきにくくなります。

識別番号やメールアドレスなどを途中で切ると、別のデータとして扱われる危険があります。

NVLでNULLを一律に置き換えると、未入力と正常な既定値を区別できなくなる場合があります。

NUMBERの精度を広げるだけでは、異常な計算結果や単位の取り違えを見逃す可能性があります。

WHEN OTHERSで全例外を処理済みにすると、障害の発見が遅れ、再処理や修復の範囲が広がることがあります。

修正方法を選ぶ前に、値を受け入れるべきか、拒否すべきか、変換すべきか、記録して再処理すべきかを決めます。

再発防止・原因別早見表・FAQ

ORA-06502を再発させないためには、型定義、入力境界、ログ、境界値テストを一つの流れとして見直します。

個別のエラーだけを直すのではなく、同じ値が通過するアプリケーション、PL/SQL、テーブル、外部出力の定義をそろえます。

障害対応で確認した内容をテスト項目やコードレビュー基準へ反映すると、同じ原因の再発を減らせます。

列定義と変数宣言のずれを減らす

テーブル列の値をそのまま受け取る変数では、列型を参照する宣言を使うとサイズや精度のずれを減らせます。

テーブル列のサイズ変更後に、PL/SQL変数だけ古い宣言のまま残る問題を防ぎやすくなります。

ただし、連結、関数、計算を加えた結果は元の列型と同じとは限らないため、式の戻り値に合わせた宣言が必要です。

複数列を連結した文字列は、各列の最大長を合計した値より長くなる可能性があります。

数値計算では、元の列より大きな精度や小数桁が必要になることがあります。

プロシージャの引数や関数の戻り値も、呼び出し元と同じ仕様書を参照できるようにします。

コードレビューでは、暗黙変換、固定長CHAR、狭すぎるNUMBER、NOT NULLへの代入を重点的に確認します。

スキーマ変更時には、関連するパッケージ、ビュー、アプリケーションのバインド定義を一覧で確認します。

境界値とマルチバイト文字をテストする

文字列では空文字、空白だけの値、最大長、日本語、絵文字、末尾空白をテストします。

最大長の一文字手前、最大長と同じ、最大長を一文字超える値を用意すると境界を確認しやすくなります。

BYTE指定の項目では、同じ文字数でも英数字と日本語でバイト数が異なるケースをテストします。

数値では0、負数、最大桁、小数部の最大桁、桁区切りを含む文字列、不正な文字列をテストします。

宣言範囲内の最大値と、範囲を一桁超える値を分けて確認します。

NULLを許可する項目と許可しない項目では、未指定、空文字、明示的なNULLの扱いを確認します。

本番障害を再現するテストでは、値そのものだけでなくNLS設定や文字コードも条件に含めます。

Rails、Java、Pythonなど複数の呼び出し元がある場合は、それぞれのドライバから同じ境界値を渡します。

修正後は正常系だけでなく、想定外の値が適切に拒否され、調査可能なログが残ることも確認します。

原因・確認箇所・修正方法の早見表

次の表は、詳細メッセージから最初に確認する場所と代表的な修正方針を整理したものです。

早見表は原因を確定するものではなく、調査を始める場所を決めるために使用します。

詳細メッセージ主な原因候補最初に確認する場所代表的な修正方針
character to number conversion error数値へ変換できない文字列入力値、TO_NUMBER、バインド型入力検証と明示変換
character string buffer too small受け取り側の長さ不足VARCHAR2、CHAR、OUTパラメータ宣言長とBYTE・CHARの見直し
null value not allowedNOT NULLへのNULL代入変数、引数、戻り値NULL発生経路の修正
number precision too largeNUMBERの精度やスケール超過数値宣言と実際の桁数精度調整と入力ルールの明確化
詳細なし発生行に複数候補があるORA-06512、代入元、代入先処理分割と確認ログの追加

character to number conversion errorでは、文字列の内容だけでなく、NLS設定と暗黙変換の有無を確認します。

character string buffer too smallでは、PL/SQL変数だけでなく、テーブル列、OUTパラメータ、ドライバ側バッファまで確認します。

null value not allowedでは、NULLを既定値へ置き換える前に、NULLが発生した業務上の理由を確認します。

number precision too largeでは、宣言を広げる前に、入力値や計算結果が仕様上正しい範囲かを確認します。

よくある質問と本番障害時の確認事項

ORA-06512が複数ある場合は、最初の発生地点と後続の呼び出し経路を分けて確認します。

最後のORA-06512だけを見ると、利用者が実行した匿名ブロックや呼び出し元を原因箇所と誤認する可能性があります。

VALUE_ERRORで捕捉できない場合は、実際のエラー番号がORA-01722など別の例外ではないかを確認します。

ORA-06502と表示されていても、例外処理の中で別のエラーへ置き換えられている場合は、元のエラースタックを確認します。

本番でしか発生しない場合は、実データ、NLS設定、文字コード、ドライバ、オブジェクト版の差を順番に比較します。

特定の時間帯だけ発生する場合は、バッチ処理、同時実行、セッション設定の変更も確認します。

一部のデータだけで発生する場合は、文字数、バイト数、桁数、NULL、特殊文字などの共通点を探します。

型が分からない場合は、PL/SQL変数の宣言、テーブル列、プロシージャ引数、ドライバのバインド設定を順に確認します。

原因が分からないときは、変数サイズを広げる前に、エラー全文、発生行、値、型、長さ、NULL、バインドの順で証拠を集めます。

最終的な修正では、エラーが消えたことだけでなく、不正値が正しく拒否され、必要なデータが欠損せず、再発時に調査できるログが残ることを確認します。

スポンサーリンク
記事URLをコピーしました