Autonomous Database(ADB,ADW,ATP)へ、暗号化したdatapumpのダンプファイルをDBMS_DATAPUMPパッケージでimportする

####概要
Oracle CloudのAutonomous Database(ADB,ADW,ATP)へ、PL/SQLのDBMS_DATAPUMPパッケージを使って、datapumpでexportされたダンプファイルをimportすることができます。簡単なケースをこちらで説明しています。
[Autonomous Data Warehouse Cloud(ADW)へ、DBMS_DATAPUMPパッケージでimportする](https://qiita.com/ts_carp/items/79909ad94764cb57f85c)

datapumpではダンプファイルの暗号化が可能です。ここでは**暗号化されたdatapumpのダンプファイルをADWにimportする手順**を紹介します。上記の手順の応用編なので、先に上の記事を参照するとよいです。

ADBはAutonomous Data Warehouse(ADW)とAutonomous Transaction Processing(ATP)があります。本記事はADWを使って作成しています。ATPでも同様に動作します。

(参考)Autonomous Database(ADB, ADW, ATP)の使い方に関しては、下記の記事で、さまざまな場面での詳細な手順が紹介されています。使いはじめのユーザーを意識した内容です。実際に実施したいことが下記の記事にないか確認いただくとよいです。(2020/1 追記)
[Autonomous Database ハンズオンラボ（HOL）]( https://community.oracle.com/docs/DOC-1034727 )


####datapumpでのダンプファイルの暗号化
datapumpはexportのときにダンプファイルの暗号化をすることができます。暗号化する方法はいくつかあるのですが、ここではexportのときにパスワードを指定して暗号化する方法で実施します。importの際にはそのパスワードを指定する必要があります。datapumpの暗号化に関しては、下記が参考になります。
[Oracle Database データベース・ユーティリティ:エクスポート・ユーティリティのコマンドライン・モードで使用可能なパラメータ](https://docs.oracle.com/cd/E96517_01/sutil/oracle-data-pump-export-utility.html#GUID-16EEA783-A7E8-4FD3-A7B1-C92428C94C66)

概要で紹介したPL/SQLのDBMS_DATAPUMPパッケージでimportする手順において、PL/SQLスクリプトをSQL Developerに生成させました。DBMS_DATAPUMPパッケージには設定項目が多いからです。ただし**DBMS_DATAPUMPパッケージはパスワードで暗号化されたダンプファイルをimportすることができますが、SQL Developerは暗号化されたダンプファイルを読み込むことができません。**
ここでのSQL Developerの役割は「importのためのPL/SQLスクリプトを生成する」ことです。今回は「暗号化されてないダンプファイルをSQL Developerに読み込ませてPL/SQLスクリプトを生成させて」「必要な修正をスクリプトに加えて暗号化したダンプファイルのimportを実行する」ことで、暗号化されたダンプファイルをDBMS_DATAPUMPパッケージでimportさせることにします。

「スクリプトに加える必要な修正」というのはそれほどありません。「暗号化されてないダンプファイル」は、exportの際にデータを出力しないで定義情報（メタデータ）だけを出力させるパラメータ```CONTENT=METADATA_ONLY```を指定することにします。

なお、このような悩みはADWに対してimpdpコマンドを使える環境があれば不要です。impdpコマンドの引数の指定は、DBMS_DATAPUMPパッケージのパラメータの設定より簡単で、SQL*Developerを利用する必要がないからです。

####前提
- export対象とする表があるOracle Database環境（オンプレミス環境のDBなど）
- 作成済みのADW
- インストール済みのSQL Developer
- ダンプファイルを配置するOracle Cloudのオブジェクトストレージ

ADWの作成に関しては下記が参考になります。
[Autonomous Data Warehouse Cloud(ADW)の作成とSQL Developerからの接続](https://qiita.com/ts_carp/items/a22bdd565bdf5c6e4ea8)

SQL Developerは対象のADWにadminで接続できるようにしておいてください。

####importまでの流れ
1. exportで、暗号化されてないメタデータだけのダンプファイルと暗号化されたデータの入っているダンプファイルを用意します。
2. 二つのダンプファイルをオブジェクトストレージに配置します。
3. オブジェクトストレージにアクセスするためのAuth Tokenを作成します。
4. ADWのスキーマ上でオブジェクトストレージにアクセスするためのクレデンシャルを作成します。
5. データをimportするユーザー（スキーマ）を作成します。
6. SQL DeveloperでimportのためのPL/SQLスクリプトを生成するウィザードを実行します。ここで暗号化されてないダンプファイルを利用します。
7. 生成されたPL/SQLスクリプトを修正して暗号化されたダンプファイルのimportを実行します。
8. import実行の確認をします。

ここで2.～5.までの手順は下の記事とまったく同じなので、ここでは説明は省略します。
[Autonomous Data Warehouse Cloud(ADW)へ、DBMS_DATAPUMPパッケージでimportする](https://qiita.com/ts_carp/items/79909ad94764cb57f85c)
それ以外の手順に関して、紹介していきます。

####datapumpのexpdpコマンドでメタデータのみのダンプファイルと暗号化されたダンプファイルを生成する
exportする表のあるOracle Databaseサーバー上で、expdpコマンドで対象の表に対してメタデータだけのダンプファイルと暗号化されたダンプファイルを生成させます。ここではOracle Database 11g R2の環境を利用しています。下記のようなコマンドを実行しました。

```
expdp system/(パスワード) directory=DATAPUMP_DIR \
dumpfile=ADDRESS_PART1_NODATA.dmp LOGFILE=ADDRESS_PART1_NODATA.log \
tables=SCOTT.ADDRESS_PART1 content=METADATA_ONLY

expdp system/(パスワード) directory=DATAPUMP_DIR \
dumpfile=ADDRESS_PART1_ENCRYPTION.dmp LOGFILE=ADDRESS_PART1_ENCRYPTION.log \
tables=SCOTT.ADDRESS_PART1 encryption_password=Welcome1
```

前者のexpdpコマンドでは```content=METADATA_ONLY```と指定することで、ダンプファイルにデータは出力させません。後者のexpdpコマンドでは```encryption_password=Welcome1```と指定されたパスワードで暗号化したダンプファイルを生成させます。
「importまでの流れ」の2.～5.で説明したように、生成された2つのダンプファイルをオブジェクトストレージに配置し、Auth Token、クレデンシャル、import先のスキーマの準備を実施します。

####メタデータのみのダンプファイルにSQL DeveloperからアクセスしてimportのためのPL/SQLスクリプトを生成させる
importのためのDBMS_DATAPUMPパッケージのPL/SQLスクリプトを生成させます。これも先の記事と手順は変わりません。

[Autonomous Data Warehouse Cloud(ADW)へ、DBMS_DATAPUMPパッケージでimportする : SQL DeveloperでimportのためのPL/SQLスクリプトを生成するウィザードを実行](https://qiita.com/ts_carp/items/79909ad94764cb57f85c#sql-developer%E3%81%A7import%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEplsql%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%82%A6%E3%82%A3%E3%82%B6%E3%83%BC%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C)

ウィザードの最初のステップでオブジェクトストレージに配置されたダンプファイルを読み込ませますが、暗号化しないでメタデータだけ出力させたダンプファイル（今回の例ではADDRESS_PART1_NODATA.dmp）を指定します。ダンプファイルを指定した次の「インポート・ウィザード-ステップ2/6」でダンプファイルの中にメタ情報のあるテーブルの情報が出力されていることを確認ください。今回の例では1種類の表（ADDRESS_PART1）に関して、スキーマ名をSCOTTにしたものとnullにしたものが画面で表示されます。上記の手順のようにSQL Developerのインポート・ウィザードを進めて（インポートを実施しないで）生成されたPL/SQLスクリプトをエディタで保存します。
今回の例では、次のようなPL/SQLスクリプトが生成されます。

```
set scan off
set serveroutput on
set escape off
whenever sqlerror exit 
DECLARE
    s varchar2(1000); 
    h1 number;
    errorvarchar varchar2(100):= 'ERROR';
    tryGetStatus number := 0;
begin
    h1 := dbms_datapump.open (operation => 'IMPORT', job_mode => 'TABLE', job_name => 'IMP_SD_128-09_01_10', version => 'COMPATIBLE'); 
    tryGetStatus := 1;
    dbms_datapump.set_parameter(h1, 'TRACE', 167144-96) ; 
    dbms_datapump.set_parameter (h1, 'PARTITION_OPTIONS', 'MERGE'); 
    dbms_datapump.metadata_transform(h1, 'SEGMENT_ATTRIBUTES', 0); 
    dbms_datapump.metadata_transform(h1, 'DWCS_CVT_IOTS', 1); 
    dbms_datapump.metadata_transform(h1, 'DWCS_CVT_CONSTRAINTS', 1); 
    dbms_datapump.metadata_filter(h1, 'EXCLUDE_PATH_EXPR',         'IN (''INDEX'',''INDEXTYPE'', ''MATERIALIZED_VIEW'',''MATERIALIZED_VIEW_LOG'',         ''MATERIALIZED_ZONEMAP'', ''CLUSTER'', ''CLUSTERING'')'); 
    dbms_datapump.set_parallel(handle => h1, degree => 1); 
    dbms_datapump.add_file(handle => h1, filename => 'IMPORT-'||to_char(sysdate,'hh24_mi_ss')||'.LOG', directory => 'DATA_PUMP_DIR', filetype=>DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE); 
    dbms_datapump.set_parameter(handle => h1, name => 'KEEP_MASTER', value => 1); 
    dbms_datapump.metadata_filter(handle => h1, name => 'SCHEMA_EXPR', value => 'IN(''SCOTT'')'); 
    dbms_datapump.metadata_filter(handle => h1, name => 'NAME_EXPR', value => 'IN(''ADDRESS_PART1'')'); 
    dbms_datapump.add_file(handle => h1, filename => 'https://swiftobjectstorage.（リージョンの名前）.oraclecloud.com/v1/（テナントの名前）/（バケットの名前）/ADDRESS_PART1_NODATA.dmp', directory => 'TEST_CRED', filetype => 5); 
    dbms_datapump.set_parameter(handle => h1, name => 'INCLUDE_METADATA', value => 1); 
    dbms_datapump.set_parameter(handle => h1, name => 'DATA_ACCESS_METHOD', value => 'AUTOMATIC'); 
    dbms_datapump.set_parameter(handle => h1, name => 'SKIP_UNUSABLE_INDEXES', value => 0);
    dbms_datapump.start_job(handle => h1, skip_current => 0, abort_step => 0); 
    dbms_datapump.detach(handle => h1); 
    errorvarchar := 'NO_ERROR'; 
EXCEPTION
    WHEN OTHERS THEN
    BEGIN 
        IF ((errorvarchar = 'ERROR')AND(tryGetStatus=1)) THEN 
            DBMS_DATAPUMP.DETACH(h1);
        END IF;
    EXCEPTION 
    WHEN OTHERS THEN 
        NULL;
    END;
    RAISE;
END;
/
```

このPL/SQLスクリプトの中の次の２か所がスキーマモードでのimportとの違いになりました。

```
    h1 := dbms_datapump.open (operation => 'IMPORT', job_mode => 'SCHEMA', job_name => 'IMP_SD_138-02_44_29', version => 'COMPATIBLE'); 

```

####生成されたPL/SQLスクリプトを修正して実行する
前の手順で生成したPL/SQLスクリプトに次の2点の修正をします。
- importで読み込むファイル名をメタデータのみのダンプファイルと暗号化されたダンプファイルに変更する
- ダンプファイルの暗号化のパスワードを指定する

ファイル名の変更に関しては下記の1行を変更します。ファイル名の変更だけなのでわかりやすいと思います。

```
変更前
    dbms_datapump.add_file(handle => h1, filename => 'https://swiftobjectstorage.（リージョンの名前）.oraclecloud.com/v1/（テナントの名前）/（バケットの名前）/ADDRESS_PART1_NODATA.dmp', directory => 'TEST_CRED', filetype => 5); 
変更後
    dbms_datapump.add_file(handle => h1, filename => 'https://swiftobjectstorage.（リージョンの名前）.oraclecloud.com/v1/（テナントの名前）/（バケットの名前）/ADDRESS_PART1_ENCRYPTION.dmp', directory => 'TEST_CRED', filetype => 5); 
```

パスワードの指定ですが、下記のようにパラメータでパスワードを指定します。
```dbms_datapump.set_parameter(handle => h1, name => 'ENCRYPTION_PASSWORD', value => '（ダンプファイルを出力したときに指定したパスワード）');```
今回の例では、次のように1行追加しました。

```
追加前
    dbms_datapump.set_parameter(handle => h1, name => 'SKIP_UNUSABLE_INDEXES', value => 0);
追加後
    dbms_datapump.set_parameter(handle => h1, name => 'SKIP_UNUSABLE_INDEXES', value => 0);
    dbms_datapump.set_parameter(handle => h1, name => 'ENCRYPTION_PASSWORD', value => 'Welcome1');
```
ここの2行目が追加された行です。この2つの修正を加えたPL/SQLスクリプトをSQL DeveloperからadminでADWへ接続して実行します。こちらの手順で実行できます。

[Autonomous Data Warehouse Cloud(ADW)へ、DBMS_DATAPUMPパッケージでimportする : DBMS_DATAPUMPパッケージを利用するPL/SQLスクリプトを実行](https://qiita.com/ts_carp/items/79909ad94764cb57f85c#dbms_datapump%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8Bplsql%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E5%AE%9F%E8%A1%8C)

実行したら「PL/SQLプロシージャが正常に完了しました。」と表示されること、実行したジョブのSTATEがEXECUTINGからNOT RUNNINGとなっており完了したことを確認してください。

importが完了したら、importしたデータを検索して確認してみてください。今回の例ではimportのログは下記のように出力されていました。

```
マスター表"ADMIN"."IMP_SD_128-09_01_10"は正常にロード/アンロードされました
"ADMIN"."IMP_SD_128-09_01_10"を起動しています: 
オブジェクト型TABLE_EXPORT/TABLE/TABLEの処理中です
オブジェクト型TABLE_EXPORT/TABLE/TABLE_DATAの処理中です
. . "SCOTT"."ADDRESS_PART1"                     150.9 MB  156250行がインポートされました
オブジェクト型TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINTの処理中です
オブジェクト型TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICSの処理中です
ジョブ"ADMIN"."IMP_SD_128-09_01_10"が金 3月 22 09:29:00 2019 elapsed 0 00:00:59で正常に完了しました
```