Azure BlobからOracle DBにデータを導入する

本ブログは、[オラクル・クラウドの個人ブログ](https://qiita.com/letian/items/10152a4fec813c1b7d98)の1つです。

# 初めに
前回の記事で、OCI Object Storageから、CSV/DUMPファイルをOracle DBに導入する方法を紹介しました。この方法は、Azure Blobにも適用します。

https://qiita.com/liu-wei/items/398c91fd79a63eec6e7a

今回は、Azure BlobにあるCSVとDUMPファイルをOracle DBに導入する方法をご紹介します。

__利用条件__
 Oracle DB 19cのバージョンは、<font color="blue">19.9以上</font>です。 Oracle DB 21cのバージョンは、<font color="blue">21.3以上</font>です。

<font color=blue>Autonomous DB</font>にデータを導入するのは、とても簡単です。DBMS_CLOUDパッケージは既にインストールされているので、手動のインストールは不要です。下記のSTEP9から実施すればOKです。

※この例は、OCI上のDB19c(VM)インスタンスを利用しますが、この方法は、<font color=blue>On-P/Cloud両方のDBに、適用します</font>。

__ステップ__

* STEP1~STEP8　前回の記事のステップと同様（省略）
* [STEP 9 - クレデンシャルの作成と検証](#step-9---クレデンシャルの作成と検証)
* [STEP10 - Azure BlobからCSVファイルをDBにコピー](#step10---azure-blobからcsvファイルをdbにコピー)
* [STEP11 - Azure BlobからDUMPファイルをDBに導入](#step11---azure-blobからdumpファイルをdbに導入)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/65df863c-f30f-b8c6-7b58-a74b970bf13d.png)


# STEP 9 - クレデンシャルの作成と検証
Azure Blob上のデータをアクセスするため、クレデンシャルの作成は必要です。

__アクセスキーの取得__
Storage Accounts -> Security + Networking -> Access Keys
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/469dda62-a179-9ebe-a627-babbf0fa3954.png)

以下の画面でストレージ・アカウント名をコピーしてください。"Show Keys"をクリックし、キーの内容を表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/9218b22d-8f41-b9f4-3a64-9e6dc8449ea6.png)

キーが表示されたら、右側のコピー・マークをクリックし、コピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/e425aa83-6473-d622-e7e2-e38b9137ee0e.png)
接続の時、ストレージ・アカウント名とアクセス・キーを利用しますので、メモしておいてください。

__クレデンシャルの作成__
対象ユーザ(USER01)でPDBにログインします。(既にDBMS_CLOUDの利用権限は付与済です。)

```sql
SQL> show con_name;

CON_NAME
------------------------------
DB19C_PDB1
SQL> show user;
USER is "USER01"
SQL>
```

DBMS_CLOUDパッケージを利用し、クレデンシャルを作成します。スクリプトは、以下のようです。

BEGIN
<font color="blue">DBMS_CLOUD.CREATE_CREDENTIAL</font>(
<strong>credential_name</strong> => 'your credential name',
<strong>username</strong> => 'Access_Key_ID',
<strong>password</strong> => 'Secret_Access_Key'
);
END;
/

```sql
SQL> BEGIN
  2  DBMS_CLOUD.CREATE_CREDENTIAL(
  3  credential_name => 'AZURE_BLOB',
  4  username => 'azure2oci',
  5  password => 'Secret_Access_Key(略)'
  6  );
  7  END;
  8  /

PL/SQL procedure successfully completed.

SQL>
```

__Azure Blobのオブジェクトを取得__
Azureのコンソールより、対象オブジェクトのURLを取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/87869147-8a02-f710-6d0b-8dfb172665f1.png)


<strong>オブジェクトURL</strong>: `https://<storage_account_name>.blob.core.windows.net/<container_name>/<object_name>`
例：`https://azure2oci.blob.core.windows.net/azure2oci/channels.txt`



"<font color="blue">DBMS_CLOUD.LIST_OBJECTS</font>"を使って、Azureのコンテナーをアクセスし、オブジェクトを一覧表示します。

__コマンド：__

```sql
select * from dbms_cloud.list_objects('AZURE_BLOB','https://azure2oci.blob.core.windows.net/azure2oci/');
```

__実施例：__

```sql
SQL> col OBJECT_NAME format a15
SQL> col CHECKSUM format a35
SQL> col CREATED format a20
SQL> col LAST_MODIFIED format a20
SQL> set linesize 120
SQL> select * from dbms_cloud.list_objects('AZURE_BLOB','https://azure2oci.blob.core.windows.net/azure2oci/');

OBJECT_NAME          BYTES CHECKSUM                            CREATED              LAST_MODIFIED
--------------- ---------- ----------------------------------- -------------------- --------------------
channels.txt           104 8wJjWwy2f4FsM/reQgWcAQ==            22-OCT-21 03.31.02.0 22-OCT-21 03.31.02.0
                                                               00000 AM GMT         00000 AM GMT

SQL>
```

# STEP10 - Azure BlobからCSVファイルをDBにコピー
この例は、以下のようなCSVファイルを利用します。(Azureに保存されます。)

コンテナー名：<font color="blue">azure2oci</font>
オブジェクト名：<font color="blue">channels.txt</font>
オブジェクトの中身：

```
S,Direct Sales,Direct
T,Tele Sales,Direct
C,Catalog,Indirect
I,Internet,Indirect
P,Partners,Others
```


事前にOracle DBにテーブルを作成しておきます。(ユーザ"USER01")
__コマンド：__

```sql
CREATE TABLE CHANNELS
   (channel_id CHAR(1),
    channel_desc VARCHAR2(20),
    channel_class VARCHAR2(20)
   );
/
```

__実施例：__

```sql
SQL> show user;
USER is "USER01"
SQL> CREATE TABLE CHANNELS
  2     (channel_id CHAR(1),
  3      channel_desc VARCHAR2(20),
  4      channel_class VARCHAR2(20)
  5     );

Table created.
```

<font color="blue">DBMS_CLOUD.COPY_DATA</font>を利用し、データをコピーします。
__コマンド：__

```sql
BEGIN
DBMS_CLOUD.COPY_DATA(
    table_name =>'CHANNELS',
    credential_name =>'AZURE_Credential_Name',
    file_uri_list =>'AZURE_Object_URL',
    format => json_object('delimiter' value ',')
 );
END;
/
```

__実施例：__

```sql
SQL> BEGIN
  2   DBMS_CLOUD.COPY_DATA(
  3      table_name =>'CHANNELS',
  4      credential_name =>'AZURE_BLOB',
  5      file_uri_list =>'https://azure2oci.blob.core.windows.net/azure2oci/channels.txt',
  6      format => json_object('delimiter' value ',')
  7   );
  8  END;
  9  /

PL/SQL procedure successfully completed.

SQL>
```
コピー後、テーブルの中身を確認します。

```sql
SQL> select * from CHANNELS;

C CHANNEL_DESC         CHANNEL_CLASS
- -------------------- --------------------
S Direct Sales         Direct
T Tele Sales           Direct
C Catalog              Indirect
I Internet             Indirect
P Partners             Others

SQL>
```
ここまで、CSVファイルの導入例は完了です。

# STEP11 - Azure BlobからDUMPファイルをDBに導入
CSVのようなテキストファイルだけではなく、オブジェクト・ストレージ上のDUMPファイルもDBに導入できます。

<strong>実施ステップ</strong>：
1. <font color="blue">DBMS_CLOUD.GET_OBJECT</font>で、AzureからDUMPファイルを取得し、DBのディレクトリに保存します。
2. <font color="blue">impdp</font>コマンドで、通常のインポート処理を実施します。

__事前準備__
DUMPファイル用のディレクトリを作成し、権限を対象ユーザ(USER01)に付与します。
("/u01/app/oracle/dmp"を事前に作成しておきます。)

```sql
SQL> show user;
USER is "SYSTEM"
SQL> CREATE OR REPLACE DIRECTORY TEST_DIR AS '/u01/app/oracle/dmp/';

Directory created.

SQL> GRANT READ, WRITE ON DIRECTORY TEST_DIR TO USER01;

Grant succeeded.

SQL>
```

DUMPファイルの作成処理とAzureへのファイル転送は、ここで省略します。
Azureコンソールで確認：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/9a5f86d9-cdfe-0f20-77db-2f972bc81225.png)


SQLPlusから、以下のコマンドで確認できます。

```sql
select * from dbms_cloud.list_objects('AZURE_BLOB','https://azure2oci.blob.core.windows.net/azure2oci/');
```

実施例:

```sql
SQL> show user;
USER is "USER01"
SQL> col OBJECT_NAME format a15
SQL> col CHECKSUM format a35
SQL> col CREATED format a20
SQL> col LAST_MODIFIED format a20
SQL> set linesize 120
SQL> select * from dbms_cloud.list_objects('AZURE_BLOB','https://azure2oci.blob.core.windows.net/azure2oci/');

OBJECT_NAME          BYTES CHECKSUM                            CREATED              LAST_MODIFIED
--------------- ---------- ----------------------------------- -------------------- --------------------
channels.dmp        176128 nItSNQ0J9asvS+0qznsUCw==            22-OCT-21 06.26.28.0 22-OCT-21 06.26.28.0
                                                               00000 AM GMT         00000 AM GMT

channels.txt           104 8wJjWwy2f4FsM/reQgWcAQ==            22-OCT-21 03.31.02.0 22-OCT-21 03.31.02.0
                                                               00000 AM GMT         00000 AM GMT
SQL>
```

__DUMPファイルの取得__
DBMS_CLOUD.GET_OBJECTで、DUMPファイルを取得し、ディレクトリに保存します。
("USER01"で実行)

<strong>コマンド</strong>：
BEGIN
 <font color="blue">DBMS_CLOUD.GET_OBJECT</font>(
    <strong>credential_name</strong> =>'Azure_Credential_Name',
    <strong>object_uri</strong> =>'Azure_Object_URL',
    <strong>directory_name</strong> => 'Directory_Name');
END;
/

もし以下のようなエラーが発生した場合、ユーザ"<font color="blue">C##CLOUD$SERVICE</font>"にディレクトリへのアクセス権限を付与すれば回避できます。
<pre>
ERROR at line 1:
ORA-20000: ORA-29289: directory access denied
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD", line 921
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD", line 2411
ORA-06512: at line 2
</pre>

実施例：

```sql
SQL> show user
USER is "SYSTEM"
SQL> GRANT READ, WRITE ON DIRECTORY TEST_DIR TO C##CLOUD$SERVICE;

Grant succeeded.

SQL>
```

"USER01"でDBMS_CLOUD.GET_OBJECTを実施します。

```sql
SQL> show user
USER is "USER01"
SQL> BEGIN
  2       DBMS_CLOUD.GET_OBJECT(
  3       credential_name => 'AZURE_BLOB',
  4       object_uri => 'https://azure2oci.blob.core.windows.net/azure2oci/channels.dmp',
  5       directory_name => 'TEST_DIR');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL>
```

取得後、ディレクトリの下にDUMPファイルが作成されます。（既存ファイルがある場合、上書きされます。）
<pre>
[oracle@db19c dmp]$ pwd
/u01/app/oracle/dmp
[oracle@db19c dmp]$ ls -l channels.dmp
-rw-r--r-- 1 oracle asmadmin 176128 Oct 25 08:37 channels.dmp
[oracle@db19c dmp]$
</pre>

__インポート処理__
これから、impdpでインポート処理を実施します。（この例は、カラのテーブルにインポートします。）

```
[oracle@db19c dmp]$ impdp USER01/password@DB19C_PDB1 tables=CHANNELS directory=TEST_DIR dumpfile=channels.dmp logfile=impdp_channels.log ignore=y

Import: Release 19.0.0.0.0 - Production on Mon Oct 25 08:43:20 2021
Version 19.10.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Legacy Mode Active due to the following parameters:
Legacy Mode Parameter: "ignore=TRUE" Location: Command Line, Replaced with: "table_exists_action=append"
Master table "USER01"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "USER01"."SYS_IMPORT_TABLE_01":  USER01/********@DB19C_PDB1 tables=CHANNELS directory=TEST_DIR dumpfile=channels.dmp logfile=impdp_channels.log table_exists_action=append
Processing object type TABLE_EXPORT/TABLE/TABLE
Table "USER01"."CHANNELS" exists. Data will be appended to existing table but all dependent metadata will be skipped due to table_exists_action of append
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "USER01"."CHANNELS"                         6.031 KB       5 rows
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
Job "USER01"."SYS_IMPORT_TABLE_01" successfully completed at Mon Oct 25 08:43:34 2021 elapsed 0 00:00:10

[oracle@db19c dmp]$
```

インポート実施後、テーブルの内容を確認します。

```sql
SQL> show user;
USER is "USER01"
SQL> select * from channels;

C CHANNEL_DESC         CHANNEL_CLASS
- -------------------- --------------------
S Direct Sales         Direct
T Tele Sales           Direct
C Catalog              Indirect
I Internet             Indirect
P Partners             Others

SQL>
```

ここまで、DUMPファイルの導入例は完了です。

以上です。

----
__関連記事__
[オラクル・クラウドの個人ブログ一覧](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98)
[オブジェクト・ストレージからOracle DB 19c/21cにデータを導入する](https://qiita.com/liu-wei/items/398c91fd79a63eec6e7a)
[AWS S3からOracle DBにデータを導入する](https://qiita.com/liu-wei/items/2ed58265519531d09e97)