ORA-01830: date format picture ends before converting entire input string は、Oracleで日付文字列を TO_DATE や TO_TIMESTAMP で変換するとき、指定したフォーマットが入力文字列の途中までしか読み取れず、文字列の後ろに余りが残った場合に発生するエラーです。
よくあるのは、入力値が 2026-05-13 10:30:00 のように時刻まで持っているのに、フォーマットを YYYY-MM-DD までしか指定していないケースです。日付部分は読めますが、後ろの 10:30:00 が余るためORA-01830になります。
ORA-01830は、入力文字列とフォーマットモデルの長さ・要素を完全に合わせると直ります。時刻があるなら
HH24:MI:SS、小数秒があるなら FF、タイムゾーンがあるなら TZH:TZM などを追加します。日付だけが欲しい場合は、文字列を先に切り詰めるのではなく、入力仕様やカラム型に合う変換を選びます。ORA-01830とは
Oracle公式の説明では、ORA-01830は、有効な日付フォーマットで先頭部分は変換できたものの、入力文字列全体を変換し終える前にフォーマットが終わってしまった状態です。つまり、入力文字列に対してフォーマット指定が短い、または要素が足りないと考えるとわかりやすいです。
日付フォーマットの基本は OracleのTO_CHAR / TO_DATE日付フォーマット、似たエラーの ORA-01861 は ORA-01861の原因と解決方法 も確認してください。
| 入力文字列 | 指定フォーマット | 結果 |
|---|---|---|
2026-05-13 |
YYYY-MM-DD |
OK |
2026-05-13 10:30:00 |
YYYY-MM-DD |
NG: 時刻部分が余る |
2026-05-13 10:30:00 |
YYYY-MM-DD HH24:MI:SS |
OK |
2026-05-13 10:30:00.123 |
YYYY-MM-DD HH24:MI:SS |
NG: 小数秒が余る |
エラーが出たSQLを直す順番
ORA-01830は、エラー文だけを見ると抽象的ですが、直す順番はほぼ決まっています。まず実際に渡している文字列を確認し、次にフォーマットモデルがその文字列の最後の1文字まで対応しているかを見ます。最後に、保存先や比較対象のカラム型が DATE なのか TIMESTAMP なのかを合わせます。
- 入力値に時刻・小数秒・タイムゾーンが残っていないか確認する
YYYY、MM、DD、HH24、MI、SS、FFの不足を探す- 日付だけ欲しい場合は、変換後に
TRUNCするか、入力仕様を日付だけに寄せる - 暗黙変換に任せず、
TO_DATE/TO_TIMESTAMP/TO_TIMESTAMP_TZを明示する
まず入力文字列とフォーマットを並べて確認する
ORA-01830を直す最短手順は、入力文字列とフォーマットモデルを横に並べて、最後まで対応しているか確認することです。入力に時刻、小数秒、タイムゾーン、区切り文字があるのに、フォーマット側に対応する要素がなければエラーになります。
| 入力側の要素 | フォーマット側の例 | 補足 |
|---|---|---|
| 年 | YYYY |
4桁年 |
| 月 | MM |
2桁月 |
| 日 | DD |
2桁日 |
| 時 | HH24 |
24時間表記 |
| 分 | MI |
分。月のMMと混同しない |
| 秒 | SS |
秒 |
| 小数秒 | FF |
TO_TIMESTAMPで扱う |
| タイムゾーン | TZH:TZM |
+09:00など |
時刻があるのにYYYY-MM-DDだけ指定しているケース
もっとも多い原因は、入力値に時刻が含まれているのに、フォーマットが日付部分だけになっているケースです。
-- NG: 入力には時刻があるが、フォーマットは日付まで
SELECT TO_DATE('2026-05-13 10:30:00', 'YYYY-MM-DD')
FROM dual;
-- OK: 入力文字列全体に合わせる
SELECT TO_DATE('2026-05-13 10:30:00', 'YYYY-MM-DD HH24:MI:SS')
FROM dual;
時刻を切り捨てて日付だけで扱いたい場合も、まず正しく変換してから TRUNC するのが安全です。日付の切り捨ては OracleのTRUNC関数で日付を切り捨てる方法 にまとめています。
SELECT TRUNC(TO_DATE('2026-05-13 10:30:00', 'YYYY-MM-DD HH24:MI:SS')) AS order_date
FROM dual;
小数秒がある場合はTO_TIMESTAMPを使う
入力文字列に .123 や .463779 のような小数秒が含まれる場合、TO_DATE ではなく TO_TIMESTAMP を使うのが自然です。フォーマットには FF を指定します。
-- NG: 小数秒 .123 が余る
SELECT TO_DATE('2026-05-13 10:30:00.123', 'YYYY-MM-DD HH24:MI:SS')
FROM dual;
-- OK: TIMESTAMPとして小数秒まで読む
SELECT TO_TIMESTAMP('2026-05-13 10:30:00.123', 'YYYY-MM-DD HH24:MI:SS.FF')
FROM dual;
カラムが DATE 型なら秒まで、TIMESTAMP 型なら小数秒まで扱えます。入力値の精度と保存先の型を合わせて考えます。
タイムゾーン付き文字列のケース
2026-05-13 10:30:00 +09:00 のようにタイムゾーンが付いている場合、通常の TO_DATE や TO_TIMESTAMP では後ろのタイムゾーン部分が余ることがあります。タイムゾーンまで扱うなら TO_TIMESTAMP_TZ を検討します。
SELECT TO_TIMESTAMP_TZ(
'2026-05-13 10:30:00 +09:00',
'YYYY-MM-DD HH24:MI:SS TZH:TZM'
) AS created_at
FROM dual;
WHERE句で文字列日付を比較しているケース
Java、PHP、バッチなどからSQLを組み立てるとき、日付カラムと文字列をそのまま比較してORA-01830になることがあります。Oracleが暗黙変換を行い、セッションの NLS_DATE_FORMAT と入力文字列が合わないためです。
-- NG: 文字列が暗黙変換され、環境によってORA-01830になる
SELECT *
FROM orders
WHERE order_date >= '2026-05-13 00:00:00';
-- OK: TO_DATEで明示的に変換する
SELECT *
FROM orders
WHERE order_date >= TO_DATE('2026-05-13 00:00:00', 'YYYY-MM-DD HH24:MI:SS');
時刻が不要な日付だけの比較なら、DATEリテラルも使えます。現在日時や日付関数の基本は SYSDATE・SYSTIMESTAMPの違い も参考になります。
SELECT * FROM orders WHERE order_date >= DATE '2026-05-13';
INSERTで発生するケース
INSERTでも、日付カラムに文字列を入れると暗黙変換やフォーマット不一致でORA-01830になることがあります。入力値の形式を明示してから登録します。
-- NG: 文字列のままDATE列へ入れている
INSERT INTO orders (order_id, order_date)
VALUES (1, '2026-05-13 10:30:00');
-- OK: 形式を明示する
INSERT INTO orders (order_id, order_date)
VALUES (1, TO_DATE('2026-05-13 10:30:00', 'YYYY-MM-DD HH24:MI:SS'));
TO_CHARしてからTO_DATEし直す時の注意
既にDATEやTIMESTAMPとして持っている値を TO_CHAR し、さらに TO_DATE し直す処理でもORA-01830が起きます。文字列化したフォーマットと、読み戻すフォーマットが一致していないためです。
-- NG: TO_CHARでは時刻まで出しているが、TO_DATEは日付までしか読まない
SELECT TO_DATE(
TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.FF'),
'YYYY-MM-DD'
)
FROM dual;
-- OK: 文字列化と読み戻しのフォーマットを合わせる
SELECT TO_TIMESTAMP(
TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS.FF'),
'YYYY-MM-DD HH24:MI:SS.FF'
)
FROM dual;
そもそも日付型のまま処理できるなら、文字列に変換して戻す処理は避けたほうが安全です。表示のための TO_CHAR と、比較・保存のための日付型処理は分けて考えます。
ORA-01861との違い
ORA-01830 と ORA-01861 はどちらも日付フォーマット不一致で発生しますが、見方が少し違います。ORA-01830は「先頭は読めたが、入力文字列の後ろが余った」ケース、ORA-01861は「文字列とフォーマットがそもそも合っていない」ケースとして切り分けると調査しやすいです。
| エラー | 典型例 | 主な直し方 |
|---|---|---|
ORA-01830 |
2026-05-13 10:30:00 に YYYY-MM-DD |
時刻など不足している書式要素を足す |
ORA-01861 |
2026/05/13 に YYYY-MM-DD |
区切り文字や月表記などを入力に合わせる |
NLS_DATE_FORMATに依存しない
開発環境では動くのに本番や別ツールでORA-01830になる場合、暗黙変換と NLS_DATE_FORMAT の違いが原因のことがあります。SQL Developer、TOAD、JDBC、バッチでセッション設定が違うと、同じ文字列でも変換結果が変わります。
SELECT value FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';
アプリやバッチでは、NLS設定に頼らず TO_DATE、TO_TIMESTAMP、DATEリテラル、バインド変数を使って明示的に渡すのが安全です。
修正チェックリスト
| 手順 | 確認すること | 見るポイント |
|---|---|---|
| 1 | 入力文字列をそのまま確認する | 時刻・小数秒・タイムゾーンが付いていないか |
| 2 | フォーマットモデルを確認する | 入力末尾まで読める要素があるか |
| 3 | DATEかTIMESTAMPか確認する | 小数秒があるならTO_TIMESTAMPを検討する |
| 4 | 暗黙変換を避ける | 文字列比較ではなくTO_DATEやDATEリテラルを使う |
| 5 | TO_CHARとTO_DATEの往復を見直す | 文字列化と読み戻しの書式が一致しているか |
| 6 | ORA-01861と切り分ける | 余りがあるのか、最初から合っていないのか |
| 7 | NLS設定に依存していないか確認する | 環境差で再発しないようにする |
よくある質問
ORA-01830はなぜ時刻付き文字列で起きやすいですか?
入力には時刻まであるのに、フォーマットが日付までしかないケースが多いためです。YYYY-MM-DD HH24:MI:SS のように、入力文字列全体に合わせて指定します。
日付だけ欲しい場合、SUBSTRで先頭10文字にしてよいですか?
一時対応として使われることはありますが、入力形式が変わると壊れやすいです。まず正しい型へ変換し、必要なら TRUNC で日付部分にそろえる方が安全です。
TO_DATEとTO_TIMESTAMPはどう使い分けますか?
秒までのDATE値なら TO_DATE、小数秒まで扱うなら TO_TIMESTAMP、タイムゾーンまで扱うなら TO_TIMESTAMP_TZ を検討します。
DATE型に時刻は入りますか?
OracleのDATE型は年月日だけでなく時分秒も保持します。ただし小数秒は保持しないため、小数秒が必要ならTIMESTAMP型を使います。
NLS_DATE_FORMATを変えれば解決しますか?
一時的に動くことはありますが、環境依存になりやすいです。アプリやバッチでは、フォーマットを明示するか、日付型のバインド変数で渡すのが安全です。
まとめ
ORA-01830は、入力日付文字列を変換する途中でフォーマットモデルが先に終わり、文字列の後ろに余りが残ったときに発生します。まず入力文字列とフォーマットを並べて、時刻、小数秒、タイムゾーンなどが不足していないか確認します。
時刻があるなら HH24:MI:SS、小数秒があるなら TO_TIMESTAMP と FF、タイムゾーンがあるなら TO_TIMESTAMP_TZ を使います。暗黙変換やNLS設定に頼らず、入力仕様に合った明示的な変換にすることが再発防止になります。
