【Oracle】ORA-14400の原因と解決方法|inserted partition key does not map to any partition

【Oracle】ORA-14400の原因と解決方法|inserted partition key does not map to any partition Oracle

ORA-14400: inserted partition key does not map to any partition は、Oracleのパーティション表へINSERTしようとした値が、どのパーティションにも割り当てられないときに発生するエラーです。日付の月次パーティション追加漏れ、VALUES LESS THAN の境界値ミス、LISTパーティションの値不足、バッチ投入対象月のズレなどでよく起きます。

Oracle公式のエラー説明では、RangeまたはComposite Rangeでは挿入値が最後のパーティション境界を超えた場合、Listでは指定値に合うパーティションがない場合に発生するとされています。対処は、挿入値を修正するか、値を受け入れられるパーティションを追加することです。パーティション表全体の基礎は Oracleパーティションテーブル完全ガイド、運用自動化は PL/SQLパーティションテーブル運用を自動化する方法 もあわせて確認してください。

この記事で整理すること

  • ORA-14400が起きる条件
  • RANGE、LIST、INTERVALパーティションでの原因の違い
  • パーティションキー列と既存パーティション境界の確認SQL
  • 月次パーティションの追加漏れを直すSQL
  • MAXVALUE、INTERVAL、DEFAULTパーティションの使い分け
  • SQL*Loader、APPEND、バッチ投入での注意点
  • 再発防止のチェックリスト
スポンサーリンク

重複確認結果

本番DBで ORA-14400、英語メッセージ、パーティションキー、パーティション追加漏れを検索しましたが、ORA-14400単独記事は見つかりませんでした。既存にはパーティション表、パーティション運用、パーティションインデックスの記事があるため、この記事はエラー対処の入口として作成しています。

最初に結論:値に合うパーティションを追加する

ORA-14400の直接原因は、挿入しようとしたパーティションキー値に対応するパーティションが存在しないことです。まず、どの列がパーティションキーか、挿入しようとした値はいくつか、既存パーティションの境界はどこまでかを確認します。

月次パーティションが足りないALTER TABLE ... ADD PARTITION で対象月を受け入れるパーティションを追加します。
境界値を勘違いしているVALUES LESS THAN は上限値を含みません。月初や時刻付きDATEで失敗しやすいです。
LIST値が未定義対象コードのパーティションを追加するか、想定外値を受けるDEFAULTパーティションを検討します。
毎月追加したくない要件に合うならINTERVALパーティションで自動作成できる設計を検討します。

大量投入や高速ロードで同時に問題が出る場合は ダイレクト・パス・インサート完全ガイド、SQL*Loader経由なら SQL*Loader完全ガイド も関連します。

原因別の判断フロー

ORA-14400は、パーティションの種類と投入値を見ると原因を切り分けやすいです。まず対象表のパーティション方式を確認し、そのうえで投入値が境界外なのか、未定義コードなのか、将来日付なのかを見ます。

RANGEで最大境界を超えている月次・日次パーティションの追加漏れです。対象期間を受けるパーティションを追加します。
RANGEの境界値を含むと思っているVALUES LESS THAN は上限を含みません。月初日付や時刻付きDATEを確認します。
LISTで値が未定義新しいコード値がどのパーティションにも定義されていません。値を追加するかDEFAULTを検討します。
INTERVALなのに発生する初期パーティションより小さい値、複合条件、設計制約、想定外の型変換を疑います。

ORA-14400が起きる典型パターン

一番多いのは、月次や日次のRANGEパーティションで、投入対象日のパーティションを事前に作っていないケースです。特に月初、年初、将来日付、データ移行、遅延到着データで発生しやすくなります。

月次パーティション追加漏れ

range-partition-ng.sql
CREATE TABLE sales (
  sales_id   NUMBER,
  sales_date DATE NOT NULL,
  amount     NUMBER
)
PARTITION BY RANGE (sales_date) (
  PARTITION p202604 VALUES LESS THAN (DATE '2026-05-01'),
  PARTITION p202605 VALUES LESS THAN (DATE '2026-06-01')
);

-- 2026年6月分を受けるパーティションがないため ORA-14400
INSERT INTO sales (sales_id, sales_date, amount)
VALUES (1, DATE '2026-06-01', 1000);

LISTパーティションの値不足

list-partition-ng.sql
CREATE TABLE customers_by_region (
  customer_id NUMBER,
  region_code VARCHAR2(10)
)
PARTITION BY LIST (region_code) (
  PARTITION p_jp VALUES ('JP'),
  PARTITION p_us VALUES ('US')
);

-- EUを受けるパーティションがないため ORA-14400
INSERT INTO customers_by_region (customer_id, region_code)
VALUES (100, 'EU');

境界値の勘違い

VALUES LESS THAN (DATE '2026-06-01') は、2026年6月1日を含みません。2026年5月31日23:59:59までは入り得ますが、2026年6月1日00:00:00は次のパーティションが必要です。

boundary-date-note.sql
-- p202605 は 2026-06-01 未満だけを受ける
PARTITION p202605 VALUES LESS THAN (DATE '2026-06-01')

-- これは入らない。次の p202606 が必要
DATE '2026-06-01'

まずパーティションキー列を確認する

エラー対象の表で、どの列がパーティションキーになっているかを確認します。複合パーティションキーの場合、複数列の組み合わせで判断されます。

partition-key-columns.sql
SELECT name,
       object_type,
       column_name,
       column_position
FROM user_part_key_columns
WHERE name = 'SALES'
ORDER BY column_position;

SELECT table_name,
       partitioning_type,
       subpartitioning_type,
       partition_count
FROM user_part_tables
WHERE table_name = 'SALES';

アプリ側のINSERT文だけ見ていると、パーティションキー列にどんな値が入っているか見落とすことがあります。バインド変数や変換処理後の実値を確認することが重要です。

既存パーティション境界を確認する

次に、既存パーティションがどの範囲を受けているか確認します。HIGH_VALUE はLONG型なので扱いにくいですが、まずはSQL*PlusやSQL Developerで確認する用途なら次のSQLで十分です。

partition-bound-check.sql
SELECT partition_name,
       partition_position,
       high_value,
       tablespace_name,
       num_rows,
       last_analyzed
FROM user_tab_partitions
WHERE table_name = 'SALES'
ORDER BY partition_position;

DDLとして確認したい場合は DBMS_METADATA.GET_DDL を使うと、パーティション定義全体を確認できます。

partition-ddl-check.sql
SELECT DBMS_METADATA.GET_DDL('TABLE', 'SALES')
FROM dual;

DDL取得の詳細は DBMS_METADATA完全解説 も参考になります。

対象値がどのパーティションに入るか確認する

Oracleでは PARTITION FOR を使って、指定したキー値に対応するパーティションを参照できます。対応パーティションがなければ、同じ原因で失敗します。

partition-for-check.sql
-- 指定日が入るパーティションを確認する
SELECT COUNT(*)
FROM sales PARTITION FOR (DATE '2026-06-15');

-- 対応パーティションがなければエラーになるため、投入前チェックに使える

本番バッチでは、投入対象期間の最小日付・最大日付を先に集計し、その範囲を受けるパーティションがあるか確認します。

load-range-check.sql
SELECT MIN(sales_date) AS min_sales_date,
       MAX(sales_date) AS max_sales_date,
       COUNT(*)        AS row_count
FROM sales_load_work
WHERE batch_id = :batch_id;

範囲外の投入値を特定する

月次パーティション運用では、投入データの最大日付が既存パーティションの最大境界を超えていないかを確認します。HIGH_VALUE はそのまま比較しにくいため、運用上はパーティション境界を管理テーブルで持つ方法も有効です。

partition-bound-master.sql
CREATE TABLE partition_boundary_master (
  table_name      VARCHAR2(128) NOT NULL,
  partition_name  VARCHAR2(128) NOT NULL,
  lower_date      DATE,
  upper_date      DATE NOT NULL,
  CONSTRAINT pk_partition_boundary_master
    PRIMARY KEY (table_name, partition_name)
);

-- 投入データがどの管理境界にも入らない値を確認する
SELECT w.sales_date,
       COUNT(*) AS row_count
FROM sales_load_work w
WHERE w.batch_id = :batch_id
  AND NOT EXISTS (
    SELECT 1
    FROM partition_boundary_master b
    WHERE b.table_name = 'SALES'
      AND w.sales_date >= NVL(b.lower_date, DATE '0001-01-01')
      AND w.sales_date <  b.upper_date
  )
GROUP BY w.sales_date
ORDER BY w.sales_date;

LISTの未定義コードを特定する

list-value-gap-check.sql
CREATE TABLE region_partition_master (
  region_code VARCHAR2(10) PRIMARY KEY
);

INSERT INTO region_partition_master(region_code) VALUES ('JP');
INSERT INTO region_partition_master(region_code) VALUES ('US');

SELECT w.region_code,
       COUNT(*) AS row_count
FROM customers_load_work w
WHERE NOT EXISTS (
  SELECT 1
  FROM region_partition_master m
  WHERE m.region_code = w.region_code
)
GROUP BY w.region_code
ORDER BY w.region_code;

解決1:RANGEパーティションを追加する

月次パーティションが足りない場合は、次の月を受けるパーティションを追加します。VALUES LESS THAN には、そのパーティションの上限値を指定します。

add-month-partition.sql
ALTER TABLE sales
  ADD PARTITION p202606
  VALUES LESS THAN (DATE '2026-07-01')
  TABLESPACE sales_ts;

2026年6月分を受けるパーティションなら、上限は2026年7月1日です。パーティション名は pYYYYMM のように運用しやすい規則にすると、自動追加や監視が簡単になります。

解決2:MAXVALUEパーティションを用意する

想定外の将来日付を一時的に受けたい場合、RANGEパーティションの末尾に MAXVALUE パーティションを置く設計があります。ただし、何でも受けてしまうため、後から適切な月次パーティションへ分割・移動する運用が必要です。

maxvalue-partition.sql
CREATE TABLE sales (
  sales_id   NUMBER,
  sales_date DATE NOT NULL,
  amount     NUMBER
)
PARTITION BY RANGE (sales_date) (
  PARTITION p202605 VALUES LESS THAN (DATE '2026-06-01'),
  PARTITION pmax    VALUES LESS THAN (MAXVALUE)
);

-- pmaxを月次パーティションへ分割する例
ALTER TABLE sales
  SPLIT PARTITION pmax AT (DATE '2026-07-01')
  INTO (
    PARTITION p202606,
    PARTITION pmax
  );

MAXVALUEは安全弁になりますが、放置するとpmaxにデータが溜まり、パーティション設計の意味が薄れます。定期的な分割と統計情報収集をセットにします。

解決3:INTERVALパーティションを使う

毎月パーティションを手動追加する運用を避けたい場合、RANGEパーティションをINTERVALパーティションとして設計する方法があります。指定した間隔で、新しい値に応じたパーティションが自動作成されます。

interval-partition.sql
CREATE TABLE sales (
  sales_id   NUMBER,
  sales_date DATE NOT NULL,
  amount     NUMBER
)
PARTITION BY RANGE (sales_date)
INTERVAL (NUMTOYMINTERVAL(1, 'MONTH')) (
  PARTITION p202601 VALUES LESS THAN (DATE '2026-02-01')
);

-- 2026年6月のデータをINSERTすると、必要なINTERVALパーティションが作成される
INSERT INTO sales (sales_id, sales_date, amount)
VALUES (1, DATE '2026-06-15', 1000);

INTERVALパーティションは便利ですが、命名規則、表領域、古いデータの削除、ローカルインデックス、統計情報収集をどう運用するか決めておく必要があります。パーティションインデックスは Oracleパーティションインデックス完全ガイド が関連します。

INTERVALパーティションの注意点

初期境界より小さい値INTERVALは上方向の自動作成に向きます。初期パーティションより古いデータは受けられる範囲を用意します。
名前が自動生成される自動作成パーティション名は運用命名とずれることがあります。監視やメンテナンスSQLは名前依存にしすぎないようにします。
表領域設計自動作成されるパーティションをどの表領域へ置くか、容量監視とあわせて確認します。
データ品質エラーは防げない未来日付の入力ミスも受けてしまう場合があります。業務上あり得ない日付はCHECK制約や投入前検証で止めます。

解決4:LISTパーティションに値またはDEFAULTを追加する

LISTパーティションでは、挿入値がどの VALUES にも一致しないとORA-14400になります。新しいコードを正式に扱うなら個別パーティションを追加し、想定外値を一時的に受けるならDEFAULTパーティションを検討します。

add-list-partition.sql
ALTER TABLE customers_by_region
  ADD PARTITION p_eu VALUES ('EU');

-- 想定外値を受ける安全弁
ALTER TABLE customers_by_region
  ADD PARTITION p_other VALUES (DEFAULT);

DEFAULTパーティションは便利ですが、データ品質の問題を隠すことがあります。不明コードを受けたら監視やレポートで検知し、正式なパーティションへ移す運用を作ります。

SQL*LoaderやAPPEND投入での注意点

大量データロードでは、ORA-14400が出るとロード途中で失敗行が発生します。ロード前にデータの最小・最大日付、コード値の一覧を確認し、必要なパーティションを作ってから投入します。

preload-partition-check.sql
-- ロード前に対象日付範囲を確認する
SELECT MIN(sales_date) AS min_date,
       MAX(sales_date) AS max_date,
       COUNT(*)        AS rows_to_load
FROM sales_load_work;

-- LISTパーティションなら未知コードを確認する
SELECT region_code,
       COUNT(*) AS row_count
FROM customers_load_work
GROUP BY region_code
ORDER BY region_code;

APPENDや並列DMLを使う場合は、パーティション不足に加えてORA-12838にも注意します。詳しくは ORA-12838の原因と解決方法 を確認してください。

パーティション追加後に統計情報を確認する

パーティションを追加・分割した後は、統計情報の状態も確認します。特に大量ロード後やパーティション分割後は、対象パーティションまたは表全体の統計情報を収集します。

partition-stats.sql
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(
    ownname     => USER,
    tabname     => 'SALES',
    partname    => 'P202606',
    granularity => 'PARTITION',
    cascade     => TRUE
  );
END;
/

統計情報の詳しい管理は DBMS_STATSによる統計情報の手動収集・管理完全ガイド、列の組み合わせによる見積もり改善は 拡張統計完全ガイド が関連します。

ローカルインデックス・グローバルインデックスの注意点

パーティション追加だけなら影響は軽いことが多いですが、SPLIT、DROP、TRUNCATE、EXCHANGEを行う場合はインデックス状態に注意します。グローバルインデックスがUNUSABLEになる運用では、後続SQLやバッチが失敗することがあります。

ローカルインデックス表パーティションと対応して管理しやすく、月次運用と相性がよいです。
グローバルインデックス検索には有利な場合がありますが、パーティションメンテナンス時の影響を確認します。
UNUSABLE対策メンテナンス後に USER_INDEXESUSER_IND_PARTITIONS を確認します。

インデックスがUNUSABLEになった場合は ORA-01502の原因と解決方法 が関連します。

再発防止:月次パーティションを事前作成する

月次パーティション運用では、翌月・翌々月のパーティションを事前に作るジョブを用意しておくと安全です。バッチ当日に追加する運用は、失敗時の影響が大きくなります。

next-partition-check.sql
-- 次月を受けるパーティションが存在するか確認する例
SELECT partition_name,
       high_value
FROM user_tab_partitions
WHERE table_name = 'SALES'
ORDER BY partition_position DESC
FETCH FIRST 3 ROWS ONLY;

実務では、パーティション追加ジョブ、失敗通知、追加後の統計情報収集、ローカルインデックス確認までをセットにします。

避けたい対応

原因値を見ずにパーティションを追加する投入値が日付ミスやコード変換ミスの可能性があります。まず実際のパーティションキー値を確認します。
MAXVALUEに入れっぱなしにする安全弁にはなりますが、放置するとパーティション分割の意味が薄れます。
DEFAULTで不明コードを隠すデータ品質エラーを検知できなくなります。監視や棚卸しとセットにします。
統計情報を更新しない追加・分割・大量ロード後に統計が古いと、実行計画が悪化することがあります。

本番投入前チェックリスト

  • エラー対象表のパーティションキー列を確認した
  • 投入データの最小値・最大値・コード一覧を確認した
  • 既存パーティションの HIGH_VALUE を確認した
  • VALUES LESS THAN が上限値を含まないことを理解している
  • 必要な月次・日次パーティションを事前に追加した
  • LISTパーティションでは未知コードをどう扱うか決めた
  • MAXVALUEやDEFAULTを使う場合、後続の分割・棚卸し運用を決めた
  • INTERVALパーティションを使う場合、表領域・命名・統計情報収集を確認した
  • パーティション追加後にローカル/グローバルインデックス状態を確認した
  • 大量ロード後にパーティション統計を収集する手順を用意した

まとめ

ORA-14400は、INSERTしようとしたパーティションキー値に対応するパーティションが存在しない時に発生します。RANGEなら境界値と月次追加漏れ、LISTなら値の定義漏れ、INTERVALなら自動作成の適用条件を確認します。

対処は、挿入値を修正するか、値を受け入れるパーティションを追加することです。本番では、事前チェック、翌月パーティションの自動追加、統計情報収集、インデックス状態確認まで含めて運用化すると、月初やバッチ投入時の事故を減らせます。