ORA-01438: value larger than specified precision allowed for this column は、Oracleで数値列に入りきらない値を INSERT または UPDATE しようとしたときに発生するエラーです。日本語にすると「この列に指定された精度より大きい値です」という意味です。
原因はたいてい、対象列が NUMBER(5,2) や NUMBER(3) のように桁数を制限しているのに、アプリ、SQL、CSV、バッチ取込から想定より大きい数値が入ってきていることです。文字列長の問題ではなく、数値の精度とスケールの問題として切り分けます。
ORA-01438は、まず対象列の
DATA_PRECISION と DATA_SCALE を確認します。NUMBER(p,s) なら、整数部に入れられる桁数は基本的に p - s 桁です。値を小さくする、取込前に検証する、または業務上必要なら ALTER TABLE ... MODIFY で列定義を広げる、の順で直します。ORA-01438とは
Oracle公式のエラー説明では、ORA-01438は「挿入または更新しようとした数値が、列に定義された精度を超えた」状態です。つまり、SQL文の構文が間違っているというより、値と列定義の組み合わせが合っていません。
たとえば金額列を NUMBER(5,2) と定義した場合、全体で5桁、小数点以下が2桁です。整数部に使えるのは3桁なので、999.99 は入りますが、1000.00 は入りません。このような値を登録しようとするとORA-01438になります。
| 確認するもの | 見るポイント | 例 |
|---|---|---|
| 列定義 | NUMBER(p,s) の p と s |
NUMBER(5,2) |
| 実データ | 整数部と小数部の桁数 | 1234.56 は整数部4桁 |
| 発生箇所 | INSERT か UPDATE か、CSV取込か |
画面登録、バッチ、SQL*Loader |
| 修正方針 | 値を直すのか、列定義を広げるのか | NUMBER(8,2) へ変更 |
NUMBER(p,s)の精度とスケールを確認する
ORA-01438を直すには、Oracleの NUMBER(p,s) の意味を押さえる必要があります。p は精度で、保存できる有効桁数の上限です。s はスケールで、小数点以下の桁数を表します。ざっくり見るなら、整数部に使える桁数は p - s と考えると判断しやすいです。
| 列定義 | 入りやすい値 | 入りにくい値 | 理由 |
|---|---|---|---|
NUMBER(5,2) |
999.99 |
1000.00 |
整数部は3桁まで |
NUMBER(3) |
999 |
1000 |
全体で3桁まで |
NUMBER(8,0) |
99999999 |
100000000 |
整数8桁まで |
NUMBER(6,3) |
999.999 |
1000.000 |
整数部は3桁まで |
小数点以下の桁だけに注目すると見落とします。たとえば NUMBER(5,2) に対して 1234.5 は小数1桁なので一見入りそうですが、整数部が4桁のため入りません。「小数点以下が何桁か」ではなく、「列全体の有効桁数と整数部の余裕」を見ます。
一方で、NUMBER のように精度とスケールを指定していない列では、DATA_PRECISION や DATA_SCALE がNULLになることがあります。その場合は列側の桁制限が明示されていないため、ORA-01438の主な確認対象は NUMBER(5,2) のように精度が指定された列です。
まずカラム定義を確認するSQL
エラーが出たら、推測で列を広げる前に、対象テーブルの列定義を確認します。USER_TAB_COLUMNS を見ると、自分のスキーマにある列の DATA_TYPE、DATA_PRECISION、DATA_SCALE を確認できます。
SELECT table_name,
column_name,
data_type,
data_precision,
data_scale
FROM user_tab_columns
WHERE table_name = 'SALES_WORK'
ORDER BY column_id;
別スキーマのテーブルを確認する場合は ALL_TAB_COLUMNS を使います。テーブル名やスキーマ名は大文字で登録されていることが多いので、まず大文字で検索します。
SELECT owner,
table_name,
column_name,
data_type,
data_precision,
data_scale
FROM all_tab_columns
WHERE owner = 'APP_SCHEMA'
AND table_name = 'SALES_WORK'
ORDER BY column_id;
どの列が原因かわからない場合は、対象テーブルのNUMBER列だけを先に一覧化します。古いOracle環境やアプリ経由のエラーでは、エラーメッセージに列名が出ないことがあるためです。INSERT文の列リストと値の順番を、この一覧と照らし合わせます。
SELECT column_id,
column_name,
data_type,
data_precision,
data_scale
FROM user_tab_columns
WHERE table_name = 'SALES_WORK'
AND data_type = 'NUMBER'
ORDER BY column_id;
Oracleのデータディクショナリを使った確認に慣れていない場合は、OracleのINSERT/UPDATE/DELETEの基本 とあわせて、どのDMLで失敗しているかを整理すると原因を追いやすくなります。
INSERTで発生するケース
もっともわかりやすいのは、列定義より大きい値をそのまま登録しているケースです。次の例では、amount は NUMBER(5,2) なので、整数部は3桁までです。
CREATE TABLE sales_work (
amount NUMBER(5,2)
);
-- OK: 5桁以内、整数部3桁以内
INSERT INTO sales_work (amount) VALUES (999.99);
-- NG: 整数部が4桁なのでORA-01438
INSERT INTO sales_work (amount) VALUES (1234.56);
この場合は、登録値が間違っているのか、列定義が狭すぎるのかを業務ルールで判断します。金額列なのに将来的に1000以上を扱うなら、値を無理に丸めるのではなく列定義を見直すほうが自然です。
UPDATEで発生するケース
UPDATEでは、計算結果が想定より大きくなってORA-01438になることがあります。元の値は問題なくても、掛け算、加算、税率計算、レート換算などの結果が列定義を超えるパターンです。
CREATE TABLE invoice_work (
amount NUMBER(8,2),
tax_amount NUMBER(5,2)
);
-- amount が大きい行では tax_amount が NUMBER(5,2) に収まらない可能性がある
UPDATE invoice_work
SET tax_amount = amount * 0.10;
このような場合は、更新前に異常値候補を抽出します。NUMBER(5,2) なら整数部は3桁なので、絶対値が 1000 以上になる値は入りません。
SELECT amount,
amount * 0.10 AS new_tax_amount
FROM invoice_work
WHERE ABS(amount * 0.10) >= 1000;
小数点以下ではなく整数部があふれているケース
ORA-01438では、「小数点以下を2桁に丸めれば解決する」と考えがちですが、整数部が収まらない場合は丸めても解決しません。
-- NUMBER(5,2) は整数部3桁、小数部2桁 -- 小数部を丸めても整数部4桁なのでNG INSERT INTO sales_work (amount) VALUES (ROUND(1234.567, 2)); -- 整数部が3桁以内ならOK INSERT INTO sales_work (amount) VALUES (ROUND(999.994, 2));
実データを確認するときは、列定義と同じスケールに丸めた後の値だけでなく、整数部の桁数も確認します。特に外部ファイルからの取込では、想定外の単位、桁区切り、通貨換算後の値が混ざっていることがあります。
CSV・SQL*Loader取込で発生するケース
CSVや固定長ファイルの取込では、1行だけ桁の大きい値が混ざってORA-01438になることがあります。本テーブルへ直接入れると原因行を追いにくいため、まずステージングテーブルへ文字列として取り込み、検証してから本テーブルへ移す方法が安全です。
CREATE TABLE sales_stg (
amount_text VARCHAR2(50)
);
-- まず数値として解釈できない行を確認する
SELECT amount_text
FROM sales_stg
WHERE NOT REGEXP_LIKE(amount_text, '^\s*[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)\s*$');
-- NUMBER(5,2) に入れる前に、整数部が3桁を超える候補を確認する
SELECT amount_text
FROM sales_stg
WHERE REGEXP_LIKE(amount_text, '^\s*[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)\s*$')
AND ABS(TO_NUMBER(TRIM(amount_text))) >= 1000;
SQL*Loaderを使っている場合は、エラー行、badファイル、ログを確認します。取込設定そのものは Oracle SQL*Loaderの使い方 にまとめています。ORA-01438では、ファイルの型変換だけでなく、受け側のNUMBER列の桁数まで確認するのがポイントです。なお、数値でない文字列まで TO_NUMBER すると別の変換エラーになるため、先に REGEXP_LIKE などで数値形式を分けておくと調査しやすくなります。
アプリから文字列や数値を渡しているケース
アプリ側では、画面入力値やAPIレスポンスをそのままDBへ渡してORA-01438になることがあります。DBエラーだけを見るとOracle側の問題に見えますが、実際には入力チェックや単位変換の漏れが原因のこともあります。
| アプリ側で見る項目 | 確認内容 | 例 |
|---|---|---|
| 入力チェック | DB列に入る上限を超えていないか | 999.99までの列に1000以上を許可していないか |
| 単位 | 円、千円、%、倍率などを取り違えていないか | 1000円を1,000,000として渡していないか |
| 型変換 | 文字列を数値化した後の値をログに出しているか | '001234.56' が 1234.56 になる |
| 丸め処理 | 丸め・切り捨て後の値が列定義に収まるか | ROUND 後も整数部が超過していないか |
バインド変数で値を渡している場合でも、列に入らない値ならORA-01438になります。バインド変数の基本は Oracleのバインド変数の使い方、動的SQL側の組み立ては EXECUTE IMMEDIATEの使い方 も参考になります。
ROUNDやTRUNCで丸める場合の注意点
小数点以下だけが問題なら、ROUND や TRUNC で桁数を合わせる方法があります。ただし、業務上の金額や数量を勝手に丸めると、請求額、在庫数、集計値が変わります。丸めてよい項目か、丸めルールは四捨五入か切り捨てかを確認してから使います。
-- 小数点以下2桁に丸める INSERT INTO sales_work (amount) VALUES (ROUND(:amount, 2)); -- 小数点以下2桁で切り捨てる INSERT INTO sales_work (amount) VALUES (TRUNC(:amount, 2));
なお、ROUND(1234.567, 2) は 1234.57 なので、NUMBER(5,2) には入りません。丸めは小数部の調整であり、整数部の桁あふれを消す処理ではない点に注意します。
カラム定義を広げる場合
値が業務上正しいなら、列定義のほうを広げます。たとえば、NUMBER(5,2) では足りない金額列を NUMBER(8,2) に変更すると、整数部は6桁まで扱えるようになります。
ALTER TABLE sales_work MODIFY (amount NUMBER(8,2));
ただし、列定義を広げる前に、画面表示、帳票、連携先、チェック制約、アプリ側の型や桁数制限も確認します。DBだけ広げても、アプリや連携先が古い桁数のままだと別の場所でエラーになります。
ORA-12899やORA-06502との違い
ORA-01438と似た場面で出るエラーに、ORA-12899やORA-06502があります。切り分けるときは、文字列の長さなのか、数値の精度なのか、PL/SQL変数のサイズなのかを分けて考えます。
| エラー | 主な原因 | 見る場所 |
|---|---|---|
ORA-01438 |
NUMBER列の精度超過 | DATA_PRECISION、DATA_SCALE |
ORA-12899 |
文字列列の長さ超過 | VARCHAR2、CHAR、DATA_LENGTH |
ORA-06502 |
PL/SQLの数値・文字列・変換エラー | PL/SQL変数の桁数、型変換、代入先 |
文字列長のエラーなら ORA-12899の原因と解決方法、PL/SQL変数や型変換の問題なら ORA-06502の原因と解決方法 を確認してください。SQL文の構文自体が怪しい場合は、ORA-00933 や ORA-00936 の観点もあわせて見ます。
修正チェックリスト
| 手順 | 確認すること | 判断 |
|---|---|---|
| 1 | エラーが出たテーブル・列を特定する | ログ、SQL、取込エラー行を見る |
| 2 | USER_TAB_COLUMNS で列定義を確認する |
DATA_PRECISION と DATA_SCALE を見る |
| 3 | 登録・更新しようとした値を確認する | 整数部と小数部の桁数を見る |
| 4 | 値が間違いか、列定義が狭いかを判断する | 業務上の上限と照合する |
| 5 | 入力チェックや取込前検証を追加する | 同じエラーを再発させない |
| 6 | 必要なら列定義を広げる | 画面・帳票・連携先も確認する |
よくある質問
NUMBER(5,2)には何桁まで入りますか?
全体で5桁、小数点以下が2桁です。整数部は3桁までなので、正の値なら 999.99 までが目安です。1000.00 は整数部4桁のため入りません。
小数点以下を丸めればORA-01438は解決しますか?
小数部だけが原因なら解決することがあります。ただし、整数部が列定義を超えている場合は、ROUND や TRUNC を使っても解決しません。
どの列が原因かわからない場合はどうしますか?
まず実行SQLと投入値をログで確認し、対象テーブルのNUMBER列を USER_TAB_COLUMNS で一覧化します。複数列へINSERTしている場合は、列リストを明示して、値との対応を見直します。列リストなしの INSERT INTO table VALUES (...) は原因列を追いにくいため、保守性の面でも避けるのがおすすめです。
列を広げても問題ありませんか?
業務上その値が正しいなら有力な修正です。ただし、アプリ、帳票、連携先、チェック制約、インデックス、テストデータも影響を受けるため、DB列だけで判断しないようにします。
CSV取込で1行だけ失敗する場合はどう見ればよいですか?
badファイルやログで失敗行を確認し、対象列の値を見ます。一度ステージングテーブルへ文字列で取り込んでから、NUMBER列に入るか検証すると原因行を特定しやすくなります。
まとめ
ORA-01438は、OracleのNUMBER列に定義された精度を超える数値を登録・更新しようとしたときに発生します。まず USER_TAB_COLUMNS で DATA_PRECISION と DATA_SCALE を確認し、実際に入れようとしている値の整数部と小数部を照合します。
値が誤っているなら入力値や取込データを修正し、値が正しいなら列定義を広げます。丸め処理は便利ですが、業務値を変える処理なので慎重に使います。特にCSV取込やバッチ処理では、ステージングテーブルで検証してから本テーブルへ入れる構成にすると再発を防ぎやすくなります。

