【Oracle】IDENTITY Columnを利用したテーブルのEXPDP/IMPDPで自動採番列はどうなるか

Oracle12cから利用できるようになったIDENTITY Columns(自動採番列)ですが、エクスポート(EXPDP)やインポート(IMPDP)した場合の自動採番列の挙動について確認してみました。

IDENTITY Columnについて

テーブル作成時(CREATE TABLE)に項目定義として「この列は自動採番列だ」と定義できるものです。INSERT発行時に勝手に連番を採番して列に値を設定してくれます。
Oracleだとこれまではシーケンスオブジェクトを別に作成して、シーケンスオブジェクトから採番した値をキーとして利用する。なんて使い方を良くしていましたが、その必要のない「IDENTITY Columns」なるものがOracle12cから利用できるようになりました。
Oracle以外のDBMSだと以前から利用できたのですが、ようやくサポートされることになった感じですね。便利。と、ここまでは前置き。

IDENTITY Columnを利用したテーブルを作成する

テーブル作成時のDDL定義のお作法・詳細は、オンラインのリファレンスや他の方のブログ等を参考にしてください。
以下のDDL定義でIDENTITY Column列を持つテーブルを作成しますが、これはこの後の検証で利用するためのものです。

CREATE TABLE TEST_TABLE(
SEQ_ID NUMBER GENERATED ALWAYS AS IDENTITY,
NAME VERCHAR2(8)
);

IDENTITY Column列を含むテーブルのエクスポート(EXPDP)やインポート(IMPDP)した場合の挙動

実際のシステム開発の現場では、テストや移行作業のためにテーブルのバックアップをEXPDPで取得し、IMPDPで元に戻すことは多々あると思いますが、その際に「シーケンスの値は採番した状態に戻り、次のINSERT時に正しく採番出来るのか」という点が気になったので検証してみました。

実際に検証してみる

以下の手順で検証してみました。

1.IDENTITY column列を含むテーブル作成(前述で作成済み)


2.データをINSERT(シーケンスを採番する)

INSERT INTO TEST_TABLE( NAME ) VALUES(‘AAA’);
INSERT INTO TEST_TABLE( NAME ) VALUES(‘BBB’);
INSERT INTO TEST_TABLE( NAME ) VALUES(‘CCC’);
COMMIT;

SEQID NAME
1 AAA
2 BBB
3 CCC

3.一部データを削除

DELETE TEST_TABLE WHERE NAME=’AAA’;
DELETE TEST_TABLE WHERE NAME=’BBB’;
COMMIT;

SEQID NAME
3 CCC

この手順で一部データ削除を行っているのは、「データ件数!=シーケンス採番済み番号」とさせるためです。シーケンスを新規作成した場合の初期値0(最初の採番で1)となりますが、「データ件数!=シーケンス採番済み番号」の状態でも、次の採番が正しく行われるか確認したかったためのものです。

4.EXPDPでテーブルをバックアップ

EXPDP TABLES=TEST_TABLE DUMPFILE=TEST_TABLE.dmp CONTENT=ALL ※その他パラメータ割愛

5.データをINSERT(シーケンスを採番する)

INSERT INTO TEST_TABLE( NAME ) VALUES(‘XXX’);
INSERT INTO TEST_TABLE( NAME ) VALUES(‘YYY’);
COMMIT;

SEQID NAME
3 CCC
4 XXX
5 YYY

6.IMPDPでテーブルをインポートする

IMPDP TABLES=TEST_TABLE DUMPFILE=TEST_TABLE.dmp CONTENT=ALL ※その他パラメータ割愛

TABLE_EXISTS_ACTIONはREPLACEとTRUNCATEでそれぞれ検証してみます。インポート直後のテーブルの状態はどちらも同じ状態ですが・・・

SEQID NAME
3 CCC

7.IMPDPでインポート後INSERTを行った結果

INSERT INTO TEST_TABLE( NAME ) VALUES(‘ZZZ’);
COMMIT;

REPLACE指定でインポート後、INSERTした場合:

SEQID NAME
3 CCC
4 ZZZ

TRUNCATE指定でインポート、INSERTした場合:

SEQID NAME
3 CCC
6 ZZZ

結論 REPLACE指定が正義

IMPDP実行時のパラメータに「table_exists_action=replace」を指定すると、シーケンスの値も含めて復元され、次のデータINSERT時も正しいシーケンスが採番されることがわかりました。
IMPDP後のシーケンスオブジェクトをUSER_SEQUENCEで確認すると別のオブジェクトが作成されていることが分かりました。
一方、「table_exists_action=truncate」を指定した場合、インポート後、採番済みのデータは元に戻りますが、新たにINSERTして採番されたシーケンスの値は番号が飛んでしまいます。IDENTITY Column列を保有するテーブルでTRUNCATE指定は、実際の運用ではおかしなことになる可能性があります。

ご参考

上記の検証のためにはCREATE TABLEやCREATE SEQUENCE権限、またEXPDP/IMPDPのためにディレクトリオブジェクトの作成とディレクトリオブジェクトに対するREAD、WRITEの権限も必要です。
面倒臭かったり、検証用の捨て環境だったらDBAで実施するのも手です。

こちらの記事もおすすめです

ORACLE SQL*Loaderの困ったとき用のメモ

【Oracle】impdpコマンドでエラー LRM-00101

 

コメントを残す

メールアドレスが公開されることはありません。