Oracle の Data Pump Import(impdp)実行中に大量に出力される ORA-31684: Object type XX:”YY” already exists。「エラーが出たのにインポートは完了している」「このエラーは無視していいのか」と悩んだ経験はないでしょうか。本記事では ORA-31684 の発生メカニズムから、table_exists_action・EXCLUDE・REMAP_SCHEMA・CONTENT=DATA_ONLY まで、状況別の解決策を体系的に解説します。
- ORA-31684 が発生する仕組みと「エラーでも継続する」理由
- オブジェクト種別(TABLE/USER/ROLE/TABLESPACE)ごとの対処法
- table_exists_action の4オプションの使い分け(skip/append/truncate/replace)
- EXCLUDE パラメータで既存オブジェクトをスキップする方法
- REMAP_SCHEMA・CONTENT=DATA_ONLY による回避パターン
- impdp 前に実施すべき事前確認チェックリスト
ORA-31684 とは
ORA-31684 は、impdp がオブジェクトを作成しようとしたとき、同名のオブジェクトがインポート先に既に存在している場合に発生します。
ORA-31684: Object type USER:"SCOTT" already exists ORA-31684: Object type ROLE:"APP_ROLE" already exists ORA-31684: Object type TABLE:"EMP" already exists ORA-31684: Object type TABLESPACE:"USERS" already exists
このエラーは 致命的エラーではなく警告的な位置づけです。impdp はオブジェクト作成に失敗した後、そのオブジェクトへの依存オブジェクトのインポートをスキップしつつ、残りの処理を続行します。
ログに大量に出ても、インポート全体が失敗しているわけではありません。
エラーメッセージの読み方
| 項目 | 例 | 意味 |
|---|---|---|
| Object type | USER |
既存と衝突したオブジェクトの種別 |
| オブジェクト名 | "SCOTT" |
既存と衝突したオブジェクトの名前 |
ORA-31684 が出やすい Object type 一覧
| Object type | 発生タイミング | 典型的な状況 |
|---|---|---|
USER |
FULL インポート時 | インポート先にすでにユーザーが存在 |
ROLE |
FULL インポート時 | 同名のロールが存在 |
TABLESPACE |
FULL インポート時 | 同名の表領域が存在 |
TABLE |
SCHEMAS/TABLES インポート時 | 同名テーブルが存在(最多) |
INDEX |
SCHEMAS インポート時 | 同名インデックスが存在 |
SYNONYM |
SCHEMAS インポート時 | 同名シノニムが存在 |
PROCEDURE |
SCHEMAS インポート時 | 同名プロシージャが存在(上書き可) |
VIEW |
SCHEMAS インポート時 | 同名ビューが存在 |
発生パターンと対処法
パターン1:テーブルが既存(最頻出)
同名テーブルが既に存在する場合の対処は table_exists_action パラメータで制御します。
table_exists_action の4オプション比較
| オプション | 動作 | データ | 推奨場面 |
|---|---|---|---|
skip(デフォルト) |
既存テーブルをスキップ(データも投入しない) | 変更なし | 差分なし・存在確認のみ |
append |
既存テーブルはそのままでデータを追記 | 追加 | 差分データを追加したい |
truncate |
既存テーブルを TRUNCATE してからデータ投入 | 置き換え | 同じ構造でデータだけ最新化 |
replace |
既存テーブルを DROP して再作成、データ投入 | 置き換え | テーブル定義ごと最新化 |
-- データを追記(append) impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ schemas=SCOTT \ table_exists_action=append \ logfile=import.log -- テーブルを再作成して置き換え(replace) impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ schemas=SCOTT \ table_exists_action=replace \ logfile=import.log
table_exists_action=replace はテーブルを DROP して再作成するため、インデックスや制約も含めてダンプファイルの定義に戻ります。依存するビューやトリガーも DROP されるため、本番環境では注意して使用してください。
パターン2:USER / ROLE / TABLESPACE が既存(FULL インポート時)
FULL モードで別のデータベースの全体ダンプをインポートすると、USER・ROLE・TABLESPACE は既存と衝突しやすいです。これらの ORA-31684 は多くの場合無視して問題ありません(テーブルのデータは正常にインポートされます)。
EXCLUDE で特定オブジェクト種別をスキップ
-- USER・TABLESPACE・ROLE の作成をスキップしてインポート impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=fullbackup.dmp \ full=y \ exclude=USER \ exclude=TABLESPACE \ exclude=ROLE \ table_exists_action=replace \ logfile=import.log
EXCLUDE で特定オブジェクトをピンポイントにスキップ
コマンドラインで
exclude=TABLE:"IN ('T1','T2')" を指定するとシェルが引用符を解釈してエラーになることがあります。パラファイル(parfile)に記述する方法を強く推奨します(後述のFAQ参照)。
-- 特定のテーブルのみ除外(parfile 推奨・コマンドラインはエスケープが複雑) impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ schemas=SCOTT \ exclude=TABLE:\"IN (\'EMP\',\'DEPT\')\" \ logfile=import.log -- インデックスのみ除外 impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ schemas=SCOTT \ exclude=INDEX \ logfile=import.log
パターン3:スキーマを別名でインポート(REMAP_SCHEMA)
本番のダンプを開発環境に取り込む場合など、スキーマ名を変えてインポートすることで既存オブジェクトとの衝突を回避できます。
-- SCOTT スキーマの内容を SCOTT_DEV スキーマとしてインポート impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ remap_schema=SCOTT:SCOTT_DEV \ logfile=import.log
パターン4:データのみインポート(CONTENT=DATA_ONLY)
DDL(テーブル定義・インデックス定義など)のインポートを完全に省略し、データの INSERT だけを実行します。ORA-31684 は一切発生しません。
-- データのみインポート(DDL は一切実行しない) impdp system/manager \ directory=DATA_PUMP_DIR \ dumpfile=backup.dmp \ schemas=SCOTT \ content=data_only \ table_exists_action=append \ logfile=import.log
DDL をスキップするため、インポート先にテーブルが存在しない場合はデータも投入されません。
テーブル定義が存在する状態でデータを最新化する場合に最適な方法です。
content=data_only と table_exists_action の組み合わせ:
DDL は実行されないため table_exists_action は事実上 append 相当として動作します。データを上書きしたい場合は table_exists_action=truncate を一緒に指定してください。
状況別:どのパラメータを使うべきか
| 状況 | 推奨パラメータ | コマンド例 |
|---|---|---|
| 既存テーブルにデータを追加したい | table_exists_action=append |
impdp ... table_exists_action=append |
| テーブル定義ごと最新化したい | table_exists_action=replace |
impdp ... table_exists_action=replace |
| テーブルはそのままでデータのみ最新化 | content=data_only + table_exists_action=truncate |
impdp ... content=data_only table_exists_action=truncate |
| USER/ROLE/TABLESPACE の衝突を避けたい | exclude=USER exclude=ROLE exclude=TABLESPACE |
impdp ... exclude=USER exclude=TABLESPACE |
| 本番を開発環境に取り込む | remap_schema=本番:開発 |
impdp ... remap_schema=PROD:DEV |
| 特定テーブルだけスキップ | exclude=TABLE:"IN ('T1','T2')" |
impdp ... exclude=TABLE:"IN ('T1','T2')" |
impdp 実行前の事前確認チェックリスト
インポート先の既存オブジェクトを確認するSQL
-- スキーマ内のテーブル一覧 SELECT table_name FROM dba_tables WHERE owner = \'SCOTT\' ORDER BY table_name; -- スキーマ内の全オブジェクト一覧 SELECT object_name, object_type, status FROM dba_objects WHERE owner = \'SCOTT\' ORDER BY object_type, object_name; -- ユーザー一覧(FULL インポート前の確認) SELECT username FROM dba_users ORDER BY username;
チェックリスト
| 確認項目 | 推奨アクション |
|---|---|
| インポート先スキーマが存在するか | 存在する場合は table_exists_action を決定 |
| FULL インポートで USER/ROLE/TABLESPACE が衝突するか | EXCLUDE で対象を除外 |
| インポート先データのバックアップ | replace/truncate 前は必ずバックアップ |
| ダンプファイルのバージョンとターゲットDBのバージョン | ターゲット側が高いかまたは同じバージョンであること |
| ディレクトリオブジェクトが存在するか | SELECT * FROM dba_directories で確認 |
ログファイルで ORA-31684 の影響を確認する
インポート後は必ずログファイルで ORA-31684 の発生箇所と「それに伴う ORA-39111(依存オブジェクトのスキップ)」を確認します。
-- ログの末尾を確認 type import.log | findstr /I "ORA-" ← Windows grep "ORA-" import.log ← Linux -- 典型的なログの流れ ORA-31684: Object type TABLE:"EMP" already exists ORA-39111: Dependent object type INDEX:"EMP_PK" skipped -- ↑ EMP が既存のためそのインデックスもスキップされた
ORA-39111: Dependent object type ... skipped は親オブジェクトの作成失敗に連鎖してスキップされたことを示します。ORA-31684 を解消すれば ORA-39111 も連動して消えることがほとんどです。
よくある質問(FAQ)
USER/ROLE/TABLESPACE への ORA-31684 はほぼ無視して問題ありません。これらは既存環境に合わせて作成済みであることが多く、インポートが「既存を使う」形で継続されるためです。
TABLE への ORA-31684 の場合は注意が必要です。table_exists_action=skip(デフォルト)だと既存テーブルへのデータ投入もスキップされます。意図的にスキップしているか確認してください。
それが skip の正しい動作です。skip は「既存テーブルはスキップ=データも投入しない」の意味です。
既存テーブルにデータを追加したい場合は table_exists_action=append、データを置き換えたい場合は table_exists_action=truncate または replace を使ってください。
完全にゼロにするには、インポート先の既存オブジェクトを事前に DROP してから FULL インポートする方法が確実です。ただし本番環境では危険を伴うため、通常は以下を組み合わせます。
exclude=USER exclude=ROLE exclude=TABLESPACEで衝突しやすいオブジェクトを除外table_exists_action=replaceでテーブルを再作成
TABLE/USER/ROLE/TABLESPACE の ORA-31684 は大半が解消されます。ただし INDEX・SYNONYM・PROCEDURE などは table_exists_action の対象外であり、対応するオブジェクトが既存の場合は引き続き ORA-31684 が出ます。これらを完全に解消するには exclude=INDEX exclude=SYNONYM 等を追加するか、インポート前に対象オブジェクトを DROP してください。
はい、すべてのパラメータはパラファイルに記述できます。長いコマンドはパラファイルにまとめると管理しやすくなります。
-- import.par の内容 directory=DATA_PUMP_DIR dumpfile=backup.dmp schemas=SCOTT table_exists_action=replace exclude=USER exclude=TABLESPACE logfile=import.log -- 実行 impdp system/manager parfile=import.par
impdp でよく発生する関連エラーをまとめます。
| エラー | 原因 | 対処 |
|---|---|---|
| ORA-39111 | 依存オブジェクトのスキップ | 親オブジェクトの ORA-31684 を解消 |
| ORA-39082 | オブジェクト作成失敗(インデックス等) | exclude=INDEX や事前の DROP |
| ORA-39083 | テーブル作成失敗(型不一致・権限不足等) | スキーマ・権限を確認 |
| ORA-01652 | TEMP 表領域不足 | TEMP 表領域を拡張 |
| ORA-01653 | データ表領域不足 | 対象表領域を拡張 |
まとめ
| 対処法 | 使い所 | キーパラメータ |
|---|---|---|
| table_exists_action=append | 既存テーブルにデータ追加 | table_exists_action=append |
| table_exists_action=truncate | データだけ最新化(構造維持) | table_exists_action=truncate |
| table_exists_action=replace | テーブル定義ごと再作成 | table_exists_action=replace |
| EXCLUDE | USER/ROLE/TABLESPACE/特定テーブルをスキップ | exclude=USER exclude=TABLESPACE |
| CONTENT=DATA_ONLY | DDL を一切実行せずデータのみ投入 | content=data_only |
| REMAP_SCHEMA | スキーマ名を変えて衝突を回避 | remap_schema=SRC:DST |
ORA-31684 は impdp の仕様上「既存がある環境に再インポートすると必ず出る」エラーです。USER/ROLE/TABLESPACE への衝突は EXCLUDE で回避し、テーブルへの衝突は table_exists_action で動作を制御するという2つの軸を押さえれば、ほぼすべてのケースに対応できます。

