【Oracle】Data Pump で既存オブジェクトをスキップしてインポートする方法|table_exists_action=SKIP・ORA-31684 対処・不足テーブルだけ追加まで解説

【Oracle】Data Pump で既存オブジェクトをスキップしてインポートする方法|table_exists_action=SKIP・ORA-31684 対処・不足テーブルだけ追加まで解説 Oracle

Data Pump Import(impdp)で既存のテーブルがある環境にインポートする場合、既存データを上書きしたくないケースがあります。table_exists_action=SKIP を指定すれば、既に存在するテーブルはスキップし、存在しないテーブルだけをインポートできます。

本記事では、SKIP の動作と注意点、ORA-31684 エラーとの関係スキップされたテーブルの確認方法不足テーブルだけ追加するパターン、そして 4 つの table_exists_action の使い分けまで解説します。

この記事でわかること
・table_exists_action=SKIP の動作
・SKIP がデフォルトである理由と ORA-31684 の関係
・スキップされたテーブルをログで確認する方法
・SKIP で「不足テーブルだけ追加」するパターン
・SKIP / REPLACE / APPEND / TRUNCATE の使い分け判断フロー
・content=DATA_ONLY / METADATA_ONLY との組み合わせ
スポンサーリンク

table_exists_action=SKIP の動作

Shell(SKIP の基本)
# 既存テーブルをスキップしてインポート(デフォルト動作)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_export.dmp \
    logfile=hr_import.log \
    schemas=HR \
    table_exists_action=SKIP

# table_exists_action を省略しても SKIP がデフォルト
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_export.dmp \
    schemas=HR
テーブル 移行先に存在 SKIP の動作
EMPLOYEES あり スキップ(何もしない)
DEPARTMENTS あり スキップ(何もしない)
NEW_TABLE なし 作成 + データ投入
SKIP は「存在しないテーブルだけ追加」する動作
既存テーブルは一切変更せず、ダンプに含まれていて移行先に存在しないテーブルだけが作成されます。既存データを保護する最も安全なオプションです。

ORA-31684 と SKIP の関係

ログ出力例(ORA-31684)
ORA-31684: Object type TABLE:"HR"."EMPLOYEES" already exists
ORA-31684: Object type TABLE:"HR"."DEPARTMENTS" already exists
Table "HR"."NEW_TABLE" successfully imported

ORA-31684 は「オブジェクトが既に存在する」という情報メッセージであり、エラーではありません。table_exists_action=SKIP の場合、このメッセージは「スキップしました」という正常な動作報告です。

ORA-31684 は SKIP の正常動作
impdp のログに ORA-31684 が出ても慌てる必要はありません。SKIP を指定(またはデフォルト)していれば、「既存テーブルはスキップし、存在しないテーブルだけインポートした」という意味です。ログの最後の「successfully completed」を確認してください。

スキップされたテーブルを確認する方法

Shell(ログファイルからスキップされたテーブルを抽出)
# ORA-31684 の行を grep でスキップされたテーブルを確認
grep 'ORA-31684' /oracle/dpdir/hr_import.log

# 正常にインポートされたテーブルを確認
grep 'successfully imported' /oracle/dpdir/hr_import.log

# スキップ数と成功数のカウント
echo "Skipped: $(grep -c 'ORA-31684' /oracle/dpdir/hr_import.log)"
echo "Imported: $(grep -c 'successfully imported' /oracle/dpdir/hr_import.log)"
SQL(インポート後にダンプと移行先の差分を確認)
-- ダンプに含まれるテーブル一覧を確認(sqlfile で DDL だけ出力)
-- impdp hr/password directory=DP_DIR dumpfile=hr_export.dmp sqlfile=check.sql

-- 移行先のテーブル一覧
SELECT table_name FROM user_tables ORDER BY table_name;

SKIP が最適なケース

ケース 説明
不足テーブルの補完 スキーマの一部テーブルだけが欠けている環境にダンプから補完
既存データの保護 本番環境にインポートする際、既存テーブルを絶対に上書きしたくない
冪等なインポート 同じダンプを複数回実行しても結果が変わらない(2 回目以降は全スキップ)
マイグレーションの段階的実行 先にテーブルだけ作成、後からデータだけ追加(content 使い分け)

table_exists_action の 4 つのオプション比較

オプション 既存テーブル 既存データ ロールバック 用途
SKIP(デフォルト) スキップ(何もしない) 維持される 不要 既存データを保護。不足テーブルの追加
REPLACE DROP して再作成 全削除 不可(DDL) テーブルを完全に置き換え
APPEND 維持(データを追加) 維持 + 追加 COMMIT 前可 差分データの追加。主キー重複に注意
TRUNCATE 維持(TRUNCATE + 投入) 全削除 → 投入 不可(DDL) テーブル構造は維持してデータ入れ替え

判断フロー

table_exists_action の選び方
・既存テーブルに触れたくないSKIP
・既存テーブルを完全に置き換えたい(構造含む)→ REPLACE
・既存テーブルにデータを追加したいAPPEND
・テーブル構造は維持してデータだけ入れ替えたいTRUNCATE

table_exists_action の全オプションの詳細は「ORA-31684 完全解説」を参照してください。

SKIP と content の組み合わせ

組み合わせ 動作 用途
SKIP + content=ALL(デフォルト) 存在しないテーブルの構造 + データを作成 不足テーブルの完全補完
SKIP + content=METADATA_ONLY 存在しないテーブルの構造だけ作成(データなし) 空テーブルの補完
SKIP + content=DATA_ONLY テーブルが存在しなければエラー(CREATE しないため) 通常は使わない組み合わせ
Shell(不足テーブルの構造だけ補完: METADATA_ONLY + SKIP)
# 存在しないテーブルの DDL だけ実行(データは投入しない)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_export.dmp \
    schemas=HR \
    content=METADATA_ONLY \
    table_exists_action=SKIP

# 既存テーブル → スキップ
# 不足テーブル → CREATE TABLE のみ実行(データなし)
SKIP + DATA_ONLY は注意
content=DATA_ONLY は CREATE TABLE を実行しないため、テーブルが存在しない場合はデータの投入先がなくエラーになります。DATA_ONLY を使う場合は SKIP ではなく APPEND または TRUNCATE を使ってください。

EXCLUDE / INCLUDE との組み合わせ

Shell(SKIP + 特定テーブルを除外)
# 特定テーブルを除外 + 残りは SKIP で不足分だけ追加
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_export.dmp \
    schemas=HR \
    table_exists_action=SKIP \
    exclude=TABLE:\"IN ('TEMP_LOG', 'AUDIT_OLD')\"
parfile(parfile でクォート問題を回避)
# skip_import.par
directory=DP_DIR
dumpfile=hr_export.dmp
logfile=skip_import.log
schemas=HR
table_exists_action=SKIP
exclude=TABLE:"IN ('TEMP_LOG', 'AUDIT_OLD')"

テーブル以外のオブジェクトの SKIP 動作

オブジェクト 既存時の動作 備考
テーブル SKIP(ORA-31684) table_exists_action で制御
インデックス スキップ(ORA-31684) テーブルがスキップされるとインデックスもスキップ
制約 スキップ(ORA-31684) テーブルに紐づく制約もスキップ
ビュー スキップ(ORA-31684) 既存ビューは上書きされない
シーケンス スキップ(ORA-31684) 既存シーケンスの現在値は維持
プロシージャ / パッケージ 上書きされる(CREATE OR REPLACE) 注意: PL/SQL は常に上書き
トリガー 上書きされる(CREATE OR REPLACE) 同上
PL/SQL(プロシージャ / ファンクション / パッケージ / トリガー)は SKIP されない
PL/SQL オブジェクトは CREATE OR REPLACE で作成されるため、table_exists_action=SKIP でも上書きされます。既存の PL/SQL を保護したい場合は EXCLUDE=PROCEDURE,FUNCTION,PACKAGE,TRIGGER で除外してください。

実務パターン集

パターン(1): マイグレーションで不足テーブルだけ追加

Shell
# 本番スキーマに不足しているテーブルだけ追加
impdp system/password \
    directory=DP_DIR \
    dumpfile=dev_schema.dmp \
    schemas=HR \
    table_exists_action=SKIP \
    logfile=add_missing_tables.log

# ログで追加されたテーブルを確認
grep 'successfully imported' /oracle/dpdir/add_missing_tables.log

パターン(2): 安全な環境構築(冪等インポート)

Shell
# CI/CD パイプラインで毎回実行しても安全
# 1 回目: 全テーブル作成
# 2 回目以降: 全テーブルスキップ(変更なし)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=initial_schema.dmp \
    schemas=HR \
    table_exists_action=SKIP \
    logfile=setup.log

パターン(3): テーブル構造だけ補完(データなし)

Shell
# 検証環境に不足テーブルの構造だけ追加(データは後から投入)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_schema.dmp \
    schemas=HR \
    content=METADATA_ONLY \
    table_exists_action=SKIP \
    exclude=PROCEDURE,FUNCTION,PACKAGE,TRIGGER

# PL/SQL は EXCLUDE で保護(上書き防止)

パターン(4): SKIP + 後から APPEND でデータ追加

Shell
# ステップ(1): 構造だけインポート(SKIP: 既存テーブルは変更なし)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_schema.dmp \
    schemas=HR \
    content=METADATA_ONLY \
    table_exists_action=SKIP

# ステップ(2): データだけ追加(APPEND: 既存データを維持して追加)
impdp hr/password \
    directory=DP_DIR \
    dumpfile=hr_schema.dmp \
    schemas=HR \
    content=DATA_ONLY \
    table_exists_action=APPEND

よくある質問

QSKIP がデフォルトなら指定しなくてもいいですか?
Aはい。table_exists_action を省略すると SKIP がデフォルトで適用されます。ただしスクリプトに明示的に table_exists_action=SKIP と書いた方が意図が明確になり、保守性が向上します。
QSKIP でデータの更新(既存行の上書き)はできますか?
Aできません。SKIP は既存テーブルに対して一切の操作を行いません。既存行を更新したい場合は REPLACE(DROP + 再作成)、APPEND(データ追加)、TRUNCATE(データ入れ替え)を使ってください。
QORA-31684 が大量に出ますが問題ありませんか?
Atable_exists_action=SKIP の場合、ORA-31684 は正常な動作報告です。「既に存在するのでスキップした」という意味であり、エラーではありません。ログの最終行に「successfully completed」があれば問題ありません。
QPL/SQL(プロシージャ等)は SKIP で保護されますか?
A保護されません。PL/SQL は CREATE OR REPLACE で作成されるため、table_exists_action の設定に関係なく上書きされます。既存の PL/SQL を保護するには EXCLUDE=PROCEDURE,FUNCTION,PACKAGE,TRIGGER を指定してください。
QSKIP で「新しいテーブルだけ追加」した後、統計情報は収集すべきですか?
Aはい。新しく作成されたテーブルには統計情報がないため、DBMS_STATS.GATHER_SCHEMA_STATS(USER, OPTIONS => 'GATHER EMPTY') で統計が未収集のテーブルだけ収集することを推奨します。
Qビューやシーケンスも SKIP されますか?
Aはい。テーブルと同様に、既に存在するビュー・シーケンス・インデックスは ORA-31684 でスキップされます。ただし PL/SQL(プロシージャ / パッケージ / トリガー)は例外で、CREATE OR REPLACE により上書きされます

まとめ

table_exists_action=SKIP の要点をまとめます。

やりたいこと 設定
既存テーブルを保護して不足分だけ追加 table_exists_action=SKIP(デフォルト)
不足テーブルの構造だけ追加(データなし) SKIP + content=METADATA_ONLY
ORA-31684 のスキップ対象を確認 grep ‘ORA-31684’ import.log
PL/SQL の上書きを防止 EXCLUDE=PROCEDURE,FUNCTION,PACKAGE,TRIGGER
冪等なインポート(何度実行しても同じ結果) SKIP で毎回実行(2 回目以降は全スキップ)
データの追加(SKIP とは異なる) table_exists_action=APPEND
テーブルを完全に置き換え table_exists_action=REPLACE

table_exists_action の全 4 オプションの詳細は「ORA-31684 完全解説」、Data Pump の基本は「Data Pump の使い方完全ガイド」、データ保護のリストア手法は「テーブルリストア時に既存データを保護する方法」も併せて参照してください。