ORA-06502: PL/SQL: 数値または値のエラーです(英語: numeric or value error)は、PL/SQL実行時に最も頻繁に遭遇するランタイムエラーのひとつです。変数への代入時に型・精度・サイズが一致しないときに発生します。
このエラーはSQL文ではなくPL/SQLブロック内で起きるため、スタックトレースがなければ発生箇所の特定が難しいという特徴があります。本記事では発生パターンごとに原因と対処法を整理し、Oracle 12.2以降で強化されたデバッグ方法も解説します。
- ORA-06502 の発生メカニズムと主なサブコード
- VARCHAR2 バッファオーバーフローのパターンと対処法
- NUMBER 型の精度・スケール超過のパターンと対処法
- 暗黙的な型変換失敗(文字列→数値、文字列→日付)のパターン
- 文字セット変換によるバイト数超過のパターン
- FORMAT_ERROR_BACKTRACE を使った発生行の特定方法
- Oracle 12.2 以降のエラーメッセージ改善(実際の値・サイズが表示)
ORA-06502 の発生メカニズムとサブコード
ORA-06502 は単体で発生することもありますが、多くの場合サブコードと追加メッセージが付随します。サブコードが実際の原因を示しているため、まずそこを読むことが診断の第一歩です。
| 主なサブコード・追加メッセージ | 原因 |
|---|---|
| ORA-06502: PL/SQL: numeric or value error: character string buffer too small | VARCHAR2/CHAR 変数の宣言長より長い文字列を代入しようとした |
| ORA-06502: PL/SQL: numeric or value error: number precision too large | NUMBER 変数の精度(桁数)を超える値を代入しようとした |
| ORA-06502: PL/SQL: numeric or value error: character to number conversion error | 数値に変換できない文字列を NUMBER 変数に代入しようとした |
| ORA-06502: PL/SQL: numeric or value error | 上記以外の型変換・演算エラー(除算0はORA-01476) |
Oracle 12.2(12cR2)以降では、”character string buffer too small” の場合に「実際の値の長さ」と「変数の宣言長」が表示されるようになりました。例:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small (actual: 25, maximum: 10)これにより発生箇所の特定が格段に楽になりました。Oracle 19c・21c・23ai でも同様です。
パターン:VARCHAR2 バッファオーバーフロー(最多発生)
最も頻繁に発生するパターンです。PL/SQL変数の宣言長より長い文字列を代入しようとすると発生します。SQL の VARCHAR2 列はエラーにならず暗黙的に切り捨て(TRUNC)しますが、PL/SQL変数は例外を発生させます。
DECLARE
v_name VARCHAR2(10); -- 最大10文字で宣言
BEGIN
v_name := 'Hello, World!'; -- 13文字 → ORA-06502
DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
-- ORA-06502: PL/SQL: numeric or value error: character string buffer too small
DECLARE
v_name VARCHAR2(100); -- 十分な長さで宣言
BEGIN
v_name := 'Hello, World!'; -- 13文字 → 問題なし
DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
DECLARE
-- テーブルの列定義から自動的に型・長さを継承する(最も安全)
v_name employees.last_name%TYPE;
BEGIN
SELECT last_name INTO v_name FROM employees WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
-- %TYPE を使えば列の定義が変わっても自動追従する
文字列操作関数の戻り値を代入するときも注意が必要です。SUBSTR・REPLACE・CONCAT などの戻り値が変数の宣言長を超えると発生します。
DECLARE
v_short VARCHAR2(5);
v_long VARCHAR2(4000) := 'ABCDEFGHIJ';
BEGIN
-- SUBSTR(v_long, 1, 10) の戻り値は 10 文字 → v_short(5) に入らない
v_short := SUBSTR(v_long, 1, 10); -- ORA-06502
END;
/
DECLARE
v_short VARCHAR2(5);
v_long VARCHAR2(4000) := 'ABCDEFGHIJ';
BEGIN
v_short := SUBSTR(v_long, 1, 5); -- 5文字以内に切り出す
-- または
v_short := SUBSTR(v_long, 1, LENGTH(v_short)); -- 変数長で制限
END;
/
パターン:NUMBER 型の精度・スケール超過
NUMBER(p, s) 型の変数に、精度(p)またはスケール(s)を超える値を代入しようとすると発生します。
-- NUMBER(precision, scale) の仕様 -- precision: 全体の有効桁数(1〜38) -- scale: 小数点以下の桁数(-84〜127) -- 例: NUMBER(5, 2) → 最大 999.99(整数部3桁、小数部2桁) -- → 1000.00 を代入しようとすると ORA-06502 -- → 999.999 は 999.99 に丸められる(スケール超過は四捨五入されエラーにならない) -- → 1000 を代入しようとすると ORA-06502(整数部4桁で超過)
DECLARE
v_amount NUMBER(5, 2); -- 最大 999.99
BEGIN
v_amount := 10000; -- 5桁の整数 → ORA-06502: number precision too large
END;
/
DECLARE
v_amount NUMBER; -- 精度・スケール指定なし → 最大38桁、制限なし
v_price NUMBER(10, 2); -- 億単位まで対応するなら余裕を持たせる
BEGIN
v_amount := 10000; -- OK
v_price := 9999999.99; -- OK
END;
/
NUMBER(5, 2) の変数に 99.999 を代入した場合、小数部3桁目が四捨五入されて 100.00 になります(エラーにはなりません)。しかし 999.99 に四捨五入した結果が精度を超える場合(999.995 → 1000.00)はエラーになります。
パターン:文字列から数値への暗黙変換失敗
数値以外の文字列を NUMBER 型変数に代入しようとすると発生します。SQL の ORA-01722(数値が無効です)と似ていますが、こちらはPL/SQL変数への代入時に発生します。
DECLARE
v_num NUMBER;
BEGIN
v_num := 'ABC'; -- ORA-06502: character to number conversion error
v_num := '12.3.4'; -- ORA-06502: 小数点が2つ
v_num := ''; -- NULL として扱われる(エラーにはならない)
END;
/
DECLARE
v_input VARCHAR2(100) := '1234';
v_num NUMBER;
BEGIN
-- Oracle 12.2 以降: 変換可能かチェックしてから代入
IF VALIDATE_CONVERSION(v_input AS NUMBER) = 1 THEN
v_num := TO_NUMBER(v_input);
DBMS_OUTPUT.PUT_LINE('変換成功: ' || v_num);
ELSE
DBMS_OUTPUT.PUT_LINE('変換不可: ' || v_input);
END IF;
END;
/
DECLARE
v_input VARCHAR2(100) := 'ABC';
v_num NUMBER;
BEGIN
-- 変換できない場合は指定したデフォルト値を使う
v_num := TO_NUMBER(v_input DEFAULT 0 ON CONVERSION ERROR);
DBMS_OUTPUT.PUT_LINE('結果: ' || v_num); -- 結果: 0
END;
/
パターン:文字列から日付への暗黙変換失敗
DATE 型変数に文字列を代入する際、文字列の形式が NLS_DATE_FORMAT と一致しないとエラーになります。
DECLARE
v_date DATE;
BEGIN
-- NLS_DATE_FORMAT が 'DD-MON-RR' の環境で以下を実行すると ORA-06502
v_date := '2025-04-01'; -- ハイフン区切りはデフォルト形式と異なる場合がある
-- NLS_DATE_FORMAT が 'YYYY/MM/DD' でも以下はエラー
v_date := '2025年4月1日'; -- 日本語月日表記はデフォルト変換不可
END;
/
DECLARE
v_date DATE;
BEGIN
-- 書式を明示することで NLS 設定に依存しなくなる(最も安全)
v_date := TO_DATE('2025-04-01', 'YYYY-MM-DD');
v_date := TO_DATE('2025年4月1日', 'YYYY"年"MM"月"DD"日"');
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_date, 'YYYY-MM-DD'));
END;
/
DECLARE
v_input VARCHAR2(100) := 'not-a-date';
v_date DATE;
BEGIN
-- 変換失敗時にデフォルト値(SYSDATE)を使う
v_date := TO_DATE(v_input DEFAULT SYSDATE ON CONVERSION ERROR, 'YYYY-MM-DD');
DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_date, 'YYYY-MM-DD'));
END;
/
パターン:文字セット変換によるバイト数超過
VARCHAR2(n) の n がバイト単位(デフォルト)で宣言されているとき、マルチバイト文字(日本語・中国語等)を含む文字列のバイト数が宣言長を超えると発生します。
DECLARE
-- VARCHAR2(10) は BYTE 単位: UTF-8では日本語1文字 = 3バイト
-- → 10バイトに入る日本語は最大3文字
v_str VARCHAR2(10);
BEGIN
v_str := '日本語テスト'; -- 6文字 = 18バイト → ORA-06502
END;
/
DECLARE
-- VARCHAR2(10 CHAR) → 10文字(バイト数でなく文字数で制限)
v_str VARCHAR2(10 CHAR);
BEGIN
v_str := '日本語テスト'; -- 6文字 → OK(10文字まで許容)
DBMS_OUTPUT.PUT_LINE(v_str);
END;
/
-- または NLS_LENGTH_SEMANTICS = CHAR に設定することでデフォルトを変えられる
-- ALTER SESSION SET NLS_LENGTH_SEMANTICS = CHAR;
-- 文字セット AL32UTF8 (UTF-8)の環境での比較 -- 日本語1文字 = 最大3バイト(UTF-8) -- BYTE セマンティクス(デフォルト) DECLARE v_byte VARCHAR2(10); BEGIN v_byte := '日本語テスト'; END; -- ORA-06502(18バイト > 10) DECLARE v_byte VARCHAR2(10); BEGIN v_byte := '日本語'; END; -- OK(9バイト <= 10) -- CHAR セマンティクス DECLARE v_char VARCHAR2(10 CHAR); BEGIN v_char := '日本語テスト'; END; -- OK(6文字 <= 10) DECLARE v_char VARCHAR2(10 CHAR); BEGIN v_char := 'ABCDEFGHIJK'; END; -- ORA-06502(11文字 > 10)
発生箇所の特定方法:FORMAT_ERROR_BACKTRACE の活用
ORA-06502 が発生したとき、エラーメッセージだけではどの行で起きたかわかりません。DBMS_UTILITY.FORMAT_ERROR_BACKTRACE(Oracle 10g 以降)を使うことで、例外発生行の番号を取得できます。
DECLARE
v_str VARCHAR2(5);
BEGIN
v_str := 'ABCDE'; -- 行4: OK
v_str := 'ABCDEFGH'; -- 行5: ORA-06502 発生
EXCEPTION
WHEN VALUE_ERROR THEN
-- SQLERRM: エラーメッセージ
-- FORMAT_ERROR_BACKTRACE: 例外が発生した行番号を含むスタックトレース
DBMS_OUTPUT.PUT_LINE('エラー: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('発生箇所: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
-- 出力例:
-- エラー: ORA-06502: PL/SQL: numeric or value error: character string buffer too small
-- 発生箇所: ORA-06512: at line 5
END;
/
DECLARE
v_val NUMBER;
BEGIN
v_val := 'XYZ'; -- ORA-06502 発生
EXCEPTION
-- ORA-06502 は PL/SQL の VALUE_ERROR として捕捉できる
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('VALUE_ERROR をキャッチしました');
DBMS_OUTPUT.PUT_LINE('詳細: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('行番号: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
WHEN OTHERS THEN
-- 予期しないエラーはログに記録して再発生させる
DBMS_OUTPUT.PUT_LINE('予期しないエラー: ' || SQLERRM);
RAISE;
END;
/
CREATE OR REPLACE PROCEDURE process_data(p_id IN NUMBER) AS
v_name employees.last_name%TYPE;
v_email VARCHAR2(200 CHAR); -- CHAR セマンティクスで余裕を持って宣言
BEGIN
SELECT last_name, email
INTO v_name, v_email
FROM employees
WHERE employee_id = p_id;
-- メイン処理...
EXCEPTION
WHEN VALUE_ERROR THEN
-- エラーログテーブルに記録(再発分析のため backtrace も保存)
INSERT INTO error_log (log_dt, proc_name, input_id, err_code, err_msg, backtrace)
VALUES (SYSDATE, 'PROCESS_DATA', p_id,
SQLCODE, SQLERRM,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
COMMIT;
WHEN OTHERS THEN
INSERT INTO error_log (log_dt, proc_name, input_id, err_code, err_msg, backtrace)
VALUES (SYSDATE, 'PROCESS_DATA', p_id,
SQLCODE, SQLERRM,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
COMMIT;
RAISE;
END;
/
ORA-06502 を予防するコーディング規則
- 変数の長さは %TYPE で継承する:列定義が変わっても自動追従。最も効果的な予防策
- 文字列操作の戻り値は余裕を持って宣言する:REPLACE や CONCAT の結果は入力より長くなり得る
- マルチバイト文字を扱う変数は CHAR セマンティクスで宣言する:
VARCHAR2(n CHAR) - TO_NUMBER / TO_DATE は書式を明示する:NLS 設定に依存しない安全なコードになる
- Oracle 12.2+ では VALIDATE_CONVERSION で事前チェックする:変換前に確認できる
- 例外ハンドラーで VALUE_ERROR をキャッチしてログを残す:本番エラーの追跡が可能になる
まとめ
ORA-06502(PL/SQL: 数値または値のエラー)は、変数への代入時にサイズ・型・精度が合わないと発生するPL/SQLランタイムエラーです。サブコードのメッセージを正確に読むことで、原因のパターン(バッファ超過・精度超過・変換失敗)を素早く特定できます。
最も効果的な予防策は%TYPE を使った変数宣言です。また、Oracle 12.2 以降では VALIDATE_CONVERSION や DEFAULT ON CONVERSION ERROR を活用することで、変換前の安全チェックが簡潔に書けます。
例外発生時の調査には DBMS_UTILITY.FORMAT_ERROR_BACKTRACE を必ずセットで使うことで、発生行の特定が大幅に楽になります。ストアドプロシージャ・ファンクションの作成ガイドで解説している例外処理パターンと組み合わせると、本番環境でのエラー追跡が格段に改善されます。
関連するORAエラーとして、ORA-01722(数値が無効です)(SQL文での数値変換エラー)やORA-00904(無効な識別子です)も参考にしてください。

