【完全ガイド】ORA-01830: date format picture ends before converting の原因と解決方法|TO_TIMESTAMP・ISO 8601・タイムゾーンまで徹底解説

【完全ガイド】ORA-01830: date format picture ends before converting の原因と解決方法|TO_TIMESTAMP・ISO 8601・タイムゾーンまで徹底解説

Oracle で日付変換を扱う際、必ず遭遇するエラー:

SELECT TO_DATE('2026-06-15 14:30:45', 'YYYY-MM-DD') FROM DUAL;
ORA-01830: date format picture ends before converting entire input string

翻訳: 「フォーマット指定が終わったのに、入力文字列にまだ残りがある」

つまり、入力に余分な文字があるというエラー。似た日付エラーの ORA-01843: not a valid month と混同されがちですが、別の問題を示します:

  • ORA-01843: 「無効な月」(月の位置に解釈できない値)
  • ORA-01830: 「フォーマット終了後に余り」(余分な時刻・文字)

現場では:

  • REST API から取得した ISO 8601 日付(T セパレータ)
  • SQL Server / PostgreSQL からの移行データ
  • RMAN の SET UNTIL TIME 指定
  • Java LocalDateTime からの変換
  • タイムゾーン付きデータ
  • ミリ秒・マイクロ秒付き
  • 末尾の余分なスペース

これらすべてで発生します。特にマイクロサービス・REST API 時代では、ISO 8601 の YYYY-MM-DDTHH:MM:SS 形式が標準的で、Oracle の従来 TO_DATE では扱いにくい局面が急増しています。

さらに、多くの記事は**「フォーマットを合わせろ」**で終わっていますが、実務では:

  • フォーマットが動的に変わる(複数ソース混在)
  • タイムゾーン変換が必要
  • ミリ秒精度の保持
  • 柔軟な変換関数の設計
  • NLS_DATE_FORMAT との相互作用

など、深い理解が必要です。

本記事では、ORA-01830: date format picture ends before converting entire input string完全な原因と解決方法を、リファレンスとして実用的に整理します。ORA-01843 との違い、6大発生パターン、TO_DATE/TO_TIMESTAMP/TO_TIMESTAMP_TZ の使い分け、ISO 8601 対応、タイムゾーン変換、柔軟な変換関数、Rails/Java/Python 対応、実践シナリオ、予防策、FAQまで完全網羅。この1本で ORA-01830 を根本から解決できるようになります。


目次

結論:フォーマットを入力に完全一致させる

時間がない方向けに、最速の対処を先に示します。

基本原則

フォーマット文字列 = 入力文字列の構造 に完全一致させる。

-- ❌ フォーマットが短い
TO_DATE('2026-06-15 14:30:45', 'YYYY-MM-DD')

-- ✅ フォーマットを完全に
TO_DATE('2026-06-15 14:30:45', 'YYYY-MM-DD HH24:MI:SS')

よくある入力パターン別対処

-- ISO 8601 (T セパレータ)
TO_DATE('2026-06-15T14:30:45', 'YYYY-MM-DD"T"HH24:MI:SS')

-- ミリ秒付き
TO_TIMESTAMP('2026-06-15 14:30:45.123', 'YYYY-MM-DD HH24:MI:SS.FF3')

-- タイムゾーン付き
TO_TIMESTAMP_TZ('2026-06-15 14:30:45 +09:00', 
                'YYYY-MM-DD HH24:MI:SS TZH:TZM')

-- ISO 8601 完全形(Z も含む)
TO_TIMESTAMP_TZ('2026-06-15T14:30:45.123Z', 
                'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"')

3つの関数の使い分け

関数用途精度
TO_DATE秒まで
TO_TIMESTAMP少数秒ナノ秒
TO_TIMESTAMP_TZタイムゾーン付きナノ秒 + TZ

ORA-01830 vs ORA-01843

エラー意味
ORA-01830フォーマット終了後に余り
ORA-01843月の位置に無効な値

詳細は以下で解説します。


まず理解する:エラーの本質

メッセージの意味

ORA-01830: date format picture ends before converting entire input string
                                          ↑
                                     「入力を全部変換する前に」

フォーマットピクチャが終わったのに、入力文字列にまだ処理されていない部分がある

Oracle 公式の説明

Cause: A valid date format picture included extra data. 
       The first part of the format picture was converted into a valid date. 
       The remaining data was not required.

Action: Check the specifications for date format pictures and correct.

翻訳: 「フォーマットの最初の部分は有効な日付に変換されたが、残りのデータは不要」

具体例

入力:     '2026-06-15 14:30:45'
フォーマット: 'YYYY-MM-DD'

処理:
Y Y Y Y - M M - D D | 14:30:45
[----ここまで変換----]  ↑ 余分! → ORA-01830

ORA-01830 vs ORA-01843 の完全比較

-- ORA-01830: フォーマット終了後に余分
TO_DATE('2026-06-15 14:30', 'YYYY-MM-DD')
--       [変換OK]     [余分]

-- ORA-01843: 月の位置に無効な値
TO_DATE('31/12/1985', 'DD-MON-RR')
--       [DD] [??] ← '12' は月名として無効
  • ORA-01830: 「長すぎる」入力
  • ORA-01843: 「フォーマットに合わない」入力

【原因①】時刻部分がある

症状

TO_DATE('2026-06-15 14:30:45', 'YYYY-MM-DD')
-- ORA-01830

解決

-- 完全なフォーマット指定
TO_DATE('2026-06-15 14:30:45', 'YYYY-MM-DD HH24:MI:SS')

-- または日付だけ切り出し
TO_DATE(SUBSTR('2026-06-15 14:30:45', 1, 10), 'YYYY-MM-DD')

【原因②】ISO 8601 の T セパレータ

症状

REST API や JSON からの日付:

TO_DATE('2026-06-15T14:30:45', 'YYYY-MM-DD HH24:MI:SS')
-- ORA-01830(T が余分)

解決

リテラル文字として "T" を含める:

TO_DATE('2026-06-15T14:30:45', 'YYYY-MM-DD"T"HH24:MI:SS')

ダブルクォートでくくるとリテラル文字として扱う。

タイムゾーン付き ISO 8601

-- +09:00 のようなオフセット
TO_TIMESTAMP_TZ('2026-06-15T14:30:45+09:00',
                'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM')

-- Z(UTC)
TO_TIMESTAMP_TZ('2026-06-15T14:30:45Z',
                'YYYY-MM-DD"T"HH24:MI:SS"Z"')

-- ミリ秒 + タイムゾーン
TO_TIMESTAMP_TZ('2026-06-15T14:30:45.123+09:00',
                'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM')

モダン Web API の典型パターン

// JavaScript の Date.toISOString()
new Date().toISOString()
// → "2026-06-15T14:30:45.123Z"

対応する TO_TIMESTAMP_TZ:

TO_TIMESTAMP_TZ('2026-06-15T14:30:45.123Z',
                'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"')

【原因③】タイムゾーン付き

症状

TO_DATE('2026-06-15 14:30:45 +09:00', 'YYYY-MM-DD HH24:MI:SS')
-- ORA-01830(+09:00 が余分)

解決

TO_TIMESTAMP_TZ を使う:

TO_TIMESTAMP_TZ('2026-06-15 14:30:45 +09:00',
                'YYYY-MM-DD HH24:MI:SS TZH:TZM')

タイムゾーンの表現

形式フォーマット
+09:00TZH:TZM
+0900TZHTZM
JST / Asia/TokyoTZR(Time Zone Region)
PDT 等の略称TZD

内部での保持

-- 日本時間で入力
SELECT TO_TIMESTAMP_TZ('2026-06-15 14:30:45 +09:00',
                       'YYYY-MM-DD HH24:MI:SS TZH:TZM') FROM DUAL;
-- Oracle 内部で TZ 情報保持

-- UTC に変換
SELECT ... AT TIME ZONE 'UTC'

【原因④】ミリ秒・マイクロ秒

症状

TO_DATE('2026-06-15 14:30:45.123', 'YYYY-MM-DD HH24:MI:SS')
-- ORA-01830(.123 が余分)

TO_DATE は少数秒サポートなし

解決

TO_TIMESTAMP を使う:

-- ミリ秒
TO_TIMESTAMP('2026-06-15 14:30:45.123', 'YYYY-MM-DD HH24:MI:SS.FF3')

-- マイクロ秒
TO_TIMESTAMP('2026-06-15 14:30:45.123456', 'YYYY-MM-DD HH24:MI:SS.FF6')

-- ナノ秒
TO_TIMESTAMP('2026-06-15 14:30:45.123456789', 'YYYY-MM-DD HH24:MI:SS.FF9')

FF の数値

  • FF3: ミリ秒(1/1000 秒)
  • FF6: マイクロ秒(1/1000000 秒)
  • FF9: ナノ秒
  • FF(数値なし): 最大9桁

入力の少数秒桁数に合わせる


【原因⑤】末尾の余分な空白・文字

症状

TO_DATE('2026-06-15   ', 'YYYY-MM-DD')
-- ORA-01830(末尾のスペースが余分)

解決A: TRIM

TO_DATE(TRIM('2026-06-15   '), 'YYYY-MM-DD')

解決B: フォーマットに含める

TO_DATE('2026-06-15   ', 'YYYY-MM-DD"   "')
-- "   " でリテラル指定

現実的には TRIM 推奨

RTRIM で末尾のみ

TO_DATE(RTRIM('2026-06-15   '), 'YYYY-MM-DD')

【原因⑥】他 DB からのデータ取り込み

症状

SQL Server / PostgreSQL / MySQL からの取り込みで発生:

-- SQL Server から: '2026-06-15 14:30:45.1234567'
TO_DATE('2026-06-15 14:30:45.1234567', 'YYYY-MM-DD HH24:MI:SS')
-- ORA-01830

解決

TIMESTAMP 型で受ける:

CREATE TABLE imported_data (
  imported_time TIMESTAMP(7)  -- 高精度
);

INSERT INTO imported_data VALUES (
  TO_TIMESTAMP('2026-06-15 14:30:45.1234567', 'YYYY-MM-DD HH24:MI:SS.FF7')
);

JDBC / oracledb 経由

Java LocalDateTime / Python datetime を直接渡す:

// Java
ps.setTimestamp(1, Timestamp.valueOf(localDateTime));
# Python
cursor.execute("INSERT ... VALUES (:d)", d=datetime.now())

文字列化を避けるのが根本策。


3つの変換関数の使い分け

TO_DATE

TO_DATE(<string>, <format>)
  • DATE 型を返す
  • 秒までの精度(少数秒不可)
  • タイムゾーン不可

TO_TIMESTAMP

TO_TIMESTAMP(<string>, <format>)
  • TIMESTAMP 型を返す
  • 少数秒対応(FF)
  • タイムゾーン不可

TO_TIMESTAMP_TZ

TO_TIMESTAMP_TZ(<string>, <format>)
  • TIMESTAMP WITH TIME ZONE 型を返す
  • 少数秒 + タイムゾーン

選択チャート

入力に何が含まれるか?
  ↓
少数秒あり? タイムゾーンあり?
  ├─ 両方 → TO_TIMESTAMP_TZ
  ├─ 少数秒のみ → TO_TIMESTAMP
  ├─ タイムゾーンのみ → TO_TIMESTAMP_TZ
  └─ どちらもなし → TO_DATE

フォーマット文字列 完全リファレンス

日付部分

コード意味
YYYY4桁年2026
YY2桁年26
RRY2K対応2桁年26→2026
MM数値月06
MON月名略称JUN
MONTH月名フルJUNE
DD15
DDD年内日166
DAY曜日フルMONDAY
DY曜日略称MON

時刻部分

コード意味
HH12時間制02
HH2424時間制14
MI30
SS45
FF少数秒(最大9)123456789
FF3ミリ秒123
FF6マイクロ秒123456
FF9ナノ秒123456789
AM/PM午前午後PM

タイムゾーン

コード意味
TZHTZ 時+09
TZMTZ 分00
TZH:TZMTZ 時分+09:00
TZRTZ リージョン名Asia/Tokyo
TZDTZ 略称JST

リテラル文字

"任意の文字"

例:

'YYYY-MM-DD"T"HH24:MI:SS'   -- ISO 8601 T セパレータ
'YYYY-MM-DD"Z"'              -- UTC マーカー
'YYYY年MM月DD日'              -- 日本語(マルチバイトも直接OK)

FX モディファイア

厳密モード、フォーマットと入力が完全一致必要:

-- 通常: 前ゼロ許容
TO_DATE('2026-6-1', 'YYYY-MM-DD')  -- OK

-- FX: 前ゼロ必須
TO_DATE('2026-6-1', 'FXYYYY-MM-DD')  -- ORA-01862
TO_DATE('2026-06-01', 'FXYYYY-MM-DD')  -- OK

厳密な検証用。


実践パターン:柔軟な変換関数

複数フォーマット対応関数

CREATE OR REPLACE FUNCTION flexible_to_date(
  p_str VARCHAR2
) RETURN DATE AS
  v_formats SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST(
    'YYYY-MM-DD"T"HH24:MI:SS.FF"Z"',
    'YYYY-MM-DD"T"HH24:MI:SS',
    'YYYY-MM-DD HH24:MI:SS.FF',
    'YYYY-MM-DD HH24:MI:SS',
    'YYYY-MM-DD',
    'DD/MM/YYYY HH24:MI:SS',
    'DD/MM/YYYY',
    'MM/DD/YYYY HH24:MI:SS',
    'MM/DD/YYYY',
    'DD-MON-YYYY',
    'DD-MON-YY'
  );
  v_result DATE;
BEGIN
  IF p_str IS NULL THEN RETURN NULL; END IF;
  
  FOR i IN 1 .. v_formats.COUNT LOOP
    BEGIN
      v_result := TO_DATE(TRIM(p_str), v_formats(i));
      RETURN v_result;
    EXCEPTION
      WHEN OTHERS THEN NULL;
    END;
  END LOOP;
  
  RAISE_APPLICATION_ERROR(-20001, 'No matching format: ' || p_str);
END;
/

-- 使用
SELECT flexible_to_date('2026-06-15T14:30:45Z') FROM DUAL;
SELECT flexible_to_date('06/15/2026') FROM DUAL;

Oracle 12c+ の DEFAULT ON CONVERSION ERROR

TO_DATE(input DEFAULT NULL ON CONVERSION ERROR, 'YYYY-MM-DD HH24:MI:SS')

変換失敗時に NULL、バルク処理で有用。

NLS_DATE_FORMAT との相互作用

-- セッションのデフォルト日付フォーマット
SHOW PARAMETER nls_date_format

TO_DATE(str) (フォーマット指定なし)だと NLS_DATE_FORMAT が使用される。

パラメータ確認の詳細は Oracle パラメータ確認(V$PARAMETER)の記事、暗黙変換問題は ORA-01843: not a valid month の記事も参照してください。


Rails / Java / Python 対応

Rails ActiveRecord

# Rails は自動で TIMESTAMP に変換(推奨)
Order.create!(order_date: Time.current)

# 生 SQL の場合
sql = "INSERT INTO orders (order_date) VALUES (TO_TIMESTAMP(:d, 'YYYY-MM-DD HH24:MI:SS.FF'))"
ActiveRecord::Base.connection.execute(sql, d: Time.current.iso8601)

# 初期化スクリプトで NLS 設定
Rails.application.config.after_initialize do
  ActiveRecord::Base.connection.execute(
    "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
  )
  ActiveRecord::Base.connection.execute(
    "ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
  )
end

Rails 8 系の詳細は Rails 8 アップグレードガイドの記事、rails db:migrate 使い方の記事、Solid Queue 使い方の記事も参照してください。

Java (JDBC)

// ❌ 文字列で渡す(フォーマット問題の温床)
ps.setString(1, "2026-06-15T14:30:45.123Z");

// ✅ Timestamp 型で渡す
ps.setTimestamp(1, Timestamp.from(Instant.now()));

// ✅ OffsetDateTime(TZ 保持)
ps.setObject(1, OffsetDateTime.now());

Python (oracledb)

import oracledb
from datetime import datetime, timezone

# ✅ datetime 型を直接渡す(推奨)
cursor.execute(
    "INSERT INTO orders (order_date) VALUES (:d)",
    d=datetime.now(timezone.utc)
)

# ❌ 文字列で渡す
cursor.execute(
    "INSERT INTO orders (order_date) VALUES (TO_TIMESTAMP(:d, 'YYYY-MM-DD HH24:MI:SS.FF'))",
    d="2026-06-15 14:30:45.123"
)

実践シナリオ

シナリオ1:REST API の日付処理

-- API から: "2026-06-15T14:30:45.123Z"
INSERT INTO api_events (event_time)
VALUES (TO_TIMESTAMP_TZ(:api_time, 'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"'));

シナリオ2:CSV バルクインポート

-- 複数フォーマット混在の CSV
INSERT INTO orders (order_id, order_date)
SELECT order_id, flexible_to_date(order_date_str)
FROM staging_orders;

シナリオ3:Data Pump インポート後の整合

-- 別 DB からのインポートで日付列
SELECT COUNT(*) FROM imported_data 
WHERE order_date IS NULL AND order_date_str IS NOT NULL;
-- 変換失敗行を検出

Data Pump の詳細は Oracle Data Pump 使い方の記事を参照してください。

シナリオ4:RMAN の SET UNTIL TIME

RMAN> run {
  SET UNTIL TIME "TO_DATE('2026-06-15 15:15:00', 'YYYY-MM-DD HH24:MI:SS')";
  RESTORE DATABASE;
  RECOVER DATABASE;
}

完全なフォーマット指定、ORA-01830 回避。

シナリオ5:ETL パイプライン

INSERT INTO fact_events (event_time, event_type, amount)
SELECT 
  CAST(TO_TIMESTAMP_TZ(event_time_str, 
                       'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM') AS TIMESTAMP),
  event_type,
  amount
FROM staging_events
LOG ERRORS INTO staging_events_err REJECT LIMIT UNLIMITED;

LOG ERRORS の詳細は ORA-00001: unique constraint violated の記事も参考にしてください。

シナリオ6:Rails migration での datetime

class AddTimestampToOrders < ActiveRecord::Migration[8.0]
  def change
    add_column :orders, :ordered_at, :timestamp, precision: 6
  end
end

precision で少数秒桁数指定。

シナリオ7:Kamal デプロイ後の初期化

# デプロイ後の初期化スクリプトで NLS 設定
env:
  clear:
    NLS_LANG: JAPANESE_JAPAN.AL32UTF8
    NLS_DATE_FORMAT: "YYYY-MM-DD HH24:MI:SS"
    NLS_TIMESTAMP_FORMAT: "YYYY-MM-DD HH24:MI:SS.FF"

Kamal 2 デプロイの詳細は Kamal 2 デプロイの記事を参照してください。

シナリオ8:Docker Oracle での動作確認

docker exec -it oracle-xe sqlplus scott/tiger <<EOF
SELECT TO_TIMESTAMP_TZ('2026-06-15T14:30:45.123+09:00',
                       'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM') 
FROM DUAL;
EOF

Docker 関連は docker daemon 接続エラーの記事、Docker no space left on device の記事も参照してください。

シナリオ9:Solid Queue ジョブ時刻管理

-- ジョブの実行時刻
SELECT job_id,
       TO_CHAR(scheduled_at, 'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"') AS scheduled_iso
FROM solid_queue_jobs;

Solid Queue の詳細は Solid Queue 使い方の記事も参照してください。

シナリオ10:分析クエリ

-- 時系列分析
SELECT 
  TRUNC(event_time, 'HH24') AS hour,
  COUNT(*) event_count
FROM events
WHERE event_time BETWEEN 
      TO_TIMESTAMP('2026-06-15 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
  AND TO_TIMESTAMP('2026-06-16 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
GROUP BY TRUNC(event_time, 'HH24')
ORDER BY hour;

予防のベストプラクティス

1. 明示的なフォーマット指定

-- ❌ 暗黙変換
INSERT INTO t VALUES ('2026-06-15');

-- ✅ 明示的
INSERT INTO t VALUES (TO_DATE('2026-06-15', 'YYYY-MM-DD'));

2. アプリでは日付型を使う

// ❌ 文字列
ps.setString(1, dateStr);

// ✅ 日付型
ps.setTimestamp(1, timestamp);

文字列化を避けるのが根本策。

3. ISO 8601 標準を使う

2026-06-15T14:30:45.123Z

曖昧さのない標準形式

4. TIMESTAMP 型を優先

-- ❌ DATE で受ける(精度不足)
CREATE TABLE t (event_time DATE);

-- ✅ TIMESTAMP で受ける
CREATE TABLE t (event_time TIMESTAMP(6));

-- ✅ タイムゾーン対応
CREATE TABLE t (event_time TIMESTAMP(6) WITH TIME ZONE);

5. セッション初期化スクリプト

-- 統一フォーマット
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';

6. 柔軟な変換関数を用意

-- 複数フォーマット対応の関数
FUNCTION flexible_to_date(p_str VARCHAR2) RETURN DATE ...

7. LOG ERRORS でエラー分離

INSERT INTO t 
SELECT TO_DATE(col, 'YYYY-MM-DD') FROM src
LOG ERRORS INTO t_err REJECT LIMIT UNLIMITED;

8. 12c+ の ON CONVERSION ERROR

TO_DATE(str DEFAULT NULL ON CONVERSION ERROR, 'YYYY-MM-DD HH24:MI:SS')

9. 入力バリデーション

if (!input.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) {
    throw new IllegalArgumentException("Invalid date format");
}

10. テストデータの多様化

  • 秒までのみ
  • ミリ秒あり
  • タイムゾーンあり
  • ISO 8601(T セパレータ)
  • 空白付き
  • 他形式

トラブルシューティング

特定行だけエラー

-- 問題データを検出
SELECT date_str
FROM t
WHERE NOT REGEXP_LIKE(date_str, '^\d{4}-\d{2}-\d{2}$');

バルクで一部失敗

INSERT INTO target 
SELECT TO_DATE(date_str, 'YYYY-MM-DD') FROM source
LOG ERRORS INTO target_err REJECT LIMIT UNLIMITED;

-- エラー行確認
SELECT * FROM target_err WHERE ora_err_number$ = 1830;

変換関数を SQL 内で

-- 12c+
SELECT TO_DATE(str DEFAULT NULL ON CONVERSION ERROR, 'YYYY-MM-DD')
FROM t;
-- 変換失敗時に NULL

タイムゾーン変換

-- UTC → JST
SELECT event_time AT TIME ZONE 'Asia/Tokyo'
FROM events;

-- 特定 TZ で保存されているものを UTC に
SELECT event_time AT TIME ZONE 'UTC'
FROM events;

RMAN / SQL*Plus での発生

-- 完全なフォーマット指定
SET UNTIL TIME "TO_DATE('2026-06-15 15:15:00', 'YYYY-MM-DD HH24:MI:SS')";

JDBC ODBC ドライバの問題

古いドライバで ORA-01830 が頻発することあり:

  • 最新版に更新
  • パラメータバインディングを使用(文字列化を避ける)

よくある質問(FAQ)

Q1. ORA-01830 と ORA-01843 の違い

  • ORA-01830: フォーマット終了後に余り
  • ORA-01843: 月の位置に無効な値

Q2. NLS_DATE_FORMAT との関係

TO_DATE(str)(フォーマット指定なし)は NLS_DATE_FORMAT に依存。明示的指定推奨

Q3. FX モディファイアの用途

厳密な検証(前ゼロ必須、区切り文字完全一致)。

Q4. リテラル文字の “” は必須?

セパレータ文字(-, /, :)は自動認識、任意文字は “” 必須:

'YYYY-MM-DD'          -- OK(- はセパレータとして認識)
'YYYY_MM_DD'          -- 一部認識、環境依存
'YYYY"年"MM"月"DD"日"'  -- 確実

Q5. TIMESTAMP vs DATE

  • DATE: 年月日時分秒(1秒精度)
  • TIMESTAMP: 少数秒
  • TIMESTAMP WITH TIME ZONE: + TZ

用途で使い分け。

Q6. Autonomous DB での挙動

同じ挙動

Q7. AWS RDS Oracle

同じ挙動

Q8. 他 DB からの移行時の注意

  • SQL Server: datetime → OracleTIMESTAMP 精度に注意
  • PostgreSQL: timestamptz → TO_TIMESTAMP_TZ
  • MySQL: datetime → TIMESTAMP 使用

Q9. Rails では自動処理される?

ActiveRecord は基本的に自動変換。生 SQL を書く時のみ注意。

Q10. Java 21 の LocalDateTime

ps.setObject(1, LocalDateTime.now());
// oracle-jdbc が自動変換

文字列化不要

Q11. Python datetime.now()

cursor.execute("... :d", d=datetime.now())
# oracledb が自動変換

Q12. ミリ秒がないとき

TO_TIMESTAMP('2026-06-15', 'YYYY-MM-DD')
-- FF なくても OK、0 で埋められる

参考リンク

Oracle 公式


まとめ

ORA-01830: date format picture ends before converting entire input string の要点を再整理します。

エラーの本質

入力: '2026-06-15 14:30:45'
フォーマット: 'YYYY-MM-DD'
      ↓
'2026-06-15' まで変換 → '14:30:45' が余分 → ORA-01830

3つの変換関数

TO_DATE(str, fmt)          -- DATE 型、秒精度
TO_TIMESTAMP(str, fmt)     -- TIMESTAMP 型、少数秒
TO_TIMESTAMP_TZ(str, fmt)  -- TIMESTAMP WITH TZ 型

6大発生パターン

#パターン対処
時刻部分ありHH24:MI:SS 追加
ISO 8601 T セパレータ"T" リテラル
タイムゾーンTO_TIMESTAMP_TZ
ミリ秒・マイクロ秒FF3, FF6
末尾空白TRIM
他 DB データTIMESTAMP 型で受ける

フォーマット文字列 主要

YYYY-MM-DD                    2026-06-15
YYYY-MM-DD HH24:MI:SS         2026-06-15 14:30:45
YYYY-MM-DD HH24:MI:SS.FF3     2026-06-15 14:30:45.123
YYYY-MM-DD"T"HH24:MI:SS       2026-06-15T14:30:45
YYYY-MM-DD HH24:MI:SS TZH:TZM 2026-06-15 14:30:45 +09:00

ISO 8601 の対応

-- モダン Web API 標準
TO_TIMESTAMP_TZ('2026-06-15T14:30:45.123Z',
                'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"')

予防のベストプラクティス

  • 明示的なフォーマット指定
  • アプリで日付型を使う(文字列化を避ける)
  • ISO 8601 標準採用
  • TIMESTAMP 型を優先
  • セッション初期化
  • 柔軟な変換関数
  • LOG ERRORS 活用
  • 12c+ の ON CONVERSION ERROR

事故防止

  • フォーマットは入力に完全一致
  • リテラル文字は "" で囲む
  • タイムゾーンあれば TO_TIMESTAMP_TZ
  • ミリ秒あれば TO_TIMESTAMP
  • 末尾空白に TRIM

現代の推奨

  • DATE より TIMESTAMP
  • TIMESTAMP より TIMESTAMP WITH TIME ZONE(TZ 保持)
  • アプリで日付型を直接渡す
  • ISO 8601 を標準に
  • RA-01843 との使い分けを意識

これらの知識は、Oracle での日常開発・REST API 連携・データ移行・ETL・分析クエリ・Rails / Java / Python 開発など、あらゆる場面で活用できます。本記事をブックマークしておけば、ORA-01830 に出会っても迷わず的確に対処できるようになります。


本記事は2026年6月時点の情報をもとに、Oracle Database 19c〜23ai での動作確認・公式ドキュメントに基づき作成しています。Oracle のバージョンにより挙動が異なる場合があるため、最新の情報は Oracle 公式ドキュメント(docs.oracle.com)もあわせてご確認ください。