【Oracle】ORA-31684 完全解説|impdp でオブジェクトが既存の場合の対処法・EXCLUDE・table_exists_action

【Oracle】impdpでORA-31684などのエラーが出る原因と対処法まとめ Oracle

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
ORA-31684 はエラーだがインポートは継続される
このエラーは 致命的エラーではなく警告的な位置づけです。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
replace を使うとインデックス・制約も再作成される
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
content=data_only は事前にテーブルが存在している必要がある
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 が大量に出ていたら要注意
ORA-39111: Dependent object type ... skipped は親オブジェクトの作成失敗に連鎖してスキップされたことを示します。
ORA-31684 を解消すれば ORA-39111 も連動して消えることがほとんどです。

よくある質問(FAQ)

Q ORA-31684 が大量に出ているがインポートは成功している。無視して OK?
A

USER/ROLE/TABLESPACE への ORA-31684 はほぼ無視して問題ありません。これらは既存環境に合わせて作成済みであることが多く、インポートが「既存を使う」形で継続されるためです。

TABLE への ORA-31684 の場合は注意が必要です。table_exists_action=skip(デフォルト)だと既存テーブルへのデータ投入もスキップされます。意図的にスキップしているか確認してください。

Q table_exists_action=skip なのにデータがインポートされない
A

それが skip の正しい動作です。skip は「既存テーブルはスキップ=データも投入しない」の意味です。

既存テーブルにデータを追加したい場合は table_exists_action=append、データを置き換えたい場合は table_exists_action=truncate または replace を使ってください。

Q FULL インポートで ORA-31684 を完全になくすには?
A

完全にゼロにするには、インポート先の既存オブジェクトを事前に 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 してください。

Q パラファイル(parfile)で table_exists_action を指定できる?
A

はい、すべてのパラメータはパラファイルに記述できます。長いコマンドはパラファイルにまとめると管理しやすくなります。

-- 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
Q ORA-31684 の他に impdp でよく出るエラーは?
A

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つの軸を押さえれば、ほぼすべてのケースに対応できます。