[Autonomous Database] Data TransformsでObject StorageからAutonomous Databaseの連携を試してみた

# はじめに
Autonomous Database Serverlessにはさまざまなツール群が付属しています。Data Transformsもその1つであり、ELTによるデータ連携が可能です。
本記事ではObject Storageにあるファイルemp.csvに変換をかけて、Autonomous DatabaseのDEPT表と結合して新しい表FLOW_OUTP1を作成するというデータ・フローの作成、実行を試してみました。Object Storageを利用する場合とData Transformsの利用例という点で役に立つところがあるとうれしいです。なお、Object Storageを使ったときの注意点はおわりにでまとめています。
# 1.準備
## 1-1.Data Transformsの準備
[こちらのチュートリアルの事前準備](https://oracle-japan.github.io/ocitutorials/database/adb403-data-transforms/#1-%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99)を参考に、Autonomous Databaseのデータベース・ユーザtestuserにData Transformsを使用できるようにします。
## 1-2.testuserで資格証明とDEPT表を作成
Object StorageからAutonomous Databaseをターゲットにするためには、資格証明を作成する必要があるとあったので、testuserで資格証明をCRED_TESTUSERという名前で作成します。指定するユーザ名とパスワードに指定する認証トークンについては[こちらのチュートリアルの2-1.OCIオブジェクトストレージへのアクセス情報を取得](https://oracle-japan.github.io/ocitutorials/database/adb102-dataload/#2-1-oci%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%B8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97)をご覧ください。

```sql
 BEGIN  
 DBMS_CLOUD.CREATE_CREDENTIAL(
                         CREDENTIAL_NAME  => 'CRED_TESTUSER',
                         USERNAME         => 'myUsername',
                         PASSWORD         => 'LPB>Ktk(1M1SD+a]+r'
 );
 END;
```
次にtestuserでDEPT表を作成します。
```sql
CREATE TABLE DEPT
  (
  DEPTNO NUMBER(2),
  DNAME VARCHAR2(14),
  LOC VARCHAR2(13)
  CONSTRAINT dept_pk PRIMARY KEY (deptno)
  )
/ 
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
```

# 2.ソース、ターゲットへの接続の作成
Data Transformsにtestuserでログインし、メニューのConnectionsでCreate Connectionをクリックして、Connectionを作成します。
## 2-1.Autonomous Databaseの接続
Autonomous Database用のConnectionをconn_atp1という名前で作成します。作成方法は[チュートリアルの3-1 Autonomous Databaseへの接続](https://oracle-japan.github.io/ocitutorials/database/adb403-data-transforms/#3-1-autonomous-database%E3%81%B8%E3%81%AE%E6%8E%A5%E7%B6%9A)をご確認ください。
## 2-2.Object Storageの接続
Object Storage用のConnectionを作成します。Select TypeでOracle Object Storageを選択して、Nextをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/403e660c-4921-c7b3-d6df-093679df4527.png)

表示された画面で以下を環境に合わせて入力します。

+ Connection Name : conn_obj
+ Object Storage URL : https://objectstorage.Region.oraclecloud.com/n/TenancyName/b/bucketName/o
+ Region、Namespace、Bucketは入力値から導出され自動入力されます
+ Connectivity : Swift Connectivity
+ User Name：OCIユーザ名
+ Token: 認証トークン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/1388664c-4cfc-69d8-40a4-b730bceb34f4.png)

入力後、Test Connectionで接続の成功を確認し、Createをクリックします。

::: note
ConnectivityにCredentialの選択がありますが、既存のユーザーのクレデンシャルを指定してもTest Connectionで以下のエラーになりました。内部ユーザのODI_REPO_USERのクレデンシャルとなるようなので実質指定できないと考えてよさそうです。
ORA-20004: Credential "ODI_REPO_USER"."ODI" does not exist 
:::

# 3.Data Entityのインポート
次にデータ・フローで使用するデータ・エンティティをインポートします。Data TransformsホームのメニューのData Entitiesで、Import Data Entitiesをクリックします。
## 3-1.Autonomous DatabaseのData Entityのインポート
[チュートリアルの3-2. データベース内のデータをインポートする](https://oracle-japan.github.io/ocitutorials/database/adb403-data-transforms/#3-2-%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E5%86%85%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B)を参考に、DEPTをインポートします。
## 3-2.Object StorageのData Entityのインポート
Object Storageには以下のCSV形式とJSON形式のファイルがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/76887038-7281-05ba-d20c-2bca50600df0.png)

emp.csvの内容はこちらのとおりです。
```
EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO
7369,SMITH,CLERK,7902,1980-12-17,800.00,,20
7900,JAMES,CLERK,7698,1981-12-03,950.00,,30
7876,ADAMS,CLERK,7788,1983-01-12,1100.00,,20
7521,WARD,SALESMAN,7698,1981-02-22,1250.00,500.00,30
7654,MARTIN,SALESMAN,7698,1981-09-28,1250.00,1400.00,30
7934,MILLER,CLERK,7782,1982-01-23,1300.00,,10
7844,TURNER,SALESMAN,7698,1981-09-08,1500.00,0.00,30
7499,ALLEN,SALESMAN,7698,1981-02-20,1600.00,300.00,30
7782,CLARK,MANAGER,7839,1981-06-09,2450.00,,10
7698,BLAKE,MANAGER,7839,1981-05-01,2850.00,,30
7566,JONES,MANAGER,7839,1981-04-02,2975.00,,20
7788,SCOTT,ANALYST,7566,1982-12-09,3000.00,,20
7902,FORD,ANALYST,7566,1981-12-03,3000.00,,20
7839,KING,PRESIDENT,,1981-11-17,5000.00,,10
```

Data TransformsホームのメニューのData Entitiesで、Import Data Entitiesをクリックします。Mask fileterd Filesで確認すると、csvのファイルだけが表示されます。JSON形式はサポートされていないからだと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/43170b6e-fcac-0da2-401d-7c388f601031.png)
Mask fileterd Filesには何も指定せず、Startをクリックすると、ジョブが実行され、表示されているファイルをすべてImportすることができます。ジョブ完了後、Data Entitiesの画面をリフレッシュするとインポートしたデータエンティティが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/c9e7b4b1-0571-b998-9f0c-500384eef793.png)
右端の3点リーダーから、選択したData EntityのEdit、Previewが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/fdb2d655-0a7c-92eb-ca71-73bcaf7cf019.png)

:::note
Data Entitiesはインポートだけでなく新規に作成することも可能です。新規に作成したData EntityはData FlowやData Loadで利用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/8c1c18e6-3fab-f22a-1a54-fe6d41536c02.png)
:::

# 4.Data Flowの作成
ホームのメニューのProjectsで、Create Data Flowをクリックし、データ・フローを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/c85e45f1-1ec0-d30e-ad50-476a1beb67a8.png)
続けて、Add a Schemaが表示されるので利用するスキーマとして、作成したObject Storageのconnectionの情報を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/dbfeac32-1ab5-30c4-61af-2deda69ab1fb.png)
## 4-1.EMPの変換
EMPに対してSALの値が0～1000はLOW、1000から3000をMID、3000以上をHIGHとしたSAL_LEVELの列を作成するという変換を行います。
左のData EntitiesからEMPをキャンバスにドラッグします。次に上のData Transformの項目からExpressionをドラッグしたあと、EMPからExpressionへドラッグしてリンクします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/25977027-e907-945b-2f6b-8ea7a72bf8ab.png)
次にExpressionを選択し、右端のプロパティを拡大します。
新しい属性SAL_LEVELを追加します。Attributesで+をクリックすると、一番下にNEW_ATTRが追加されるので、NameをSAL_LEVELに変更し、Data TypeはVARCHARにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/dc944b4e-f96e-8346-be5f-38ff12da7164.png)
属性を追加した後、Column Mappingで入力のEMPの属性とのマッピングを行います。Auto Mapを利用すると、By Name（名前）かBy Position（位置）で自動マッピングができます。By Nameをクリックすると、SAL_LEVEL以外がマッピングされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/9d4522e4-dc8d-a0a7-8065-38fba98686c4.png)
SAL_LEVELは手動でマッピングします。SAL_LEVELの編集アイコンをクリックし、Expression Editorを表示します。SourcesのEMPからSALをExpressionの欄にドラッグし、CASE句を使って条件を記述してOKをクリックしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/8a229849-f2f1-0dc5-4407-387662aab6c8.png)
すべての属性がマッピングされたことを確認して、プロパティを縮小します。
## 4-2.DEPTとの結合
次にAutonomous DatabaseのDEPT表と結合します。
右のData EntitiesにあるAdd a Schemaをクリックし、Autonomous DatabaseのConnectionを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/98af7f10-2697-470c-9116-32c2cbdfa857.png)
左のData EntitiesからDEPTをキャンバスにドラッグします。次に上のData Transformの項目からJoinをドラッグしたあと、Expression、DEPTからJoinへドラッグしてリンクします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/ab1fc3e4-4223-ce7a-5a16-dcbc6851c3aa.png)
Joinを選択し、右端のプロパティを拡大します。
AttributesのJoin Conditionで、DEPTNOで結合する条件を記載して、縮小します。Expressionのときと同様にExpression Editorでの編集ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/2bf5786b-4c11-ad6b-e8b0-0557bd983d76.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/88af3b5b-23c8-395f-c798-a2e027e18a25.png)

::: note
SourcesにはリンクしたExpression、DEPTだけでなく、Other SourceとしてEMPも表示がされます。
:::

## 4-3.結果表の作成
変換、結合した結果をAutonomous Databaseに新しい表FLOW_OUT1として作成します。
Joinを選択して、右上のグリッド状の表のアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/389be73c-1cc6-dd81-819e-b2bc2d0cb978.png)
作成する表の定義を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/c28f308c-279e-b266-502c-3a6bdda4e3d5.png)
次に構成する列を定義します。デフォルトでは使用できるすべての属性が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/4a08b8c1-3bb5-7876-b817-6f962c1c1fc9.png)
不要な属性の削除や名前の変更、データ型の変更を行います。今回はExpressionのDEPTNOとDEPTのDEPTNOがそれぞれExpression_DEPTNO、DEPT_DEPTNOとあるため、どちらも削除することにします。属性にチェックをして、ゴミ箱アイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/0ba90111-c573-8660-b901-fc0ac11663db.png)
Nextをクリックし、Previewで確認後Saveします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/a8209667-417b-5ee0-8d62-e7399c1508ec.png)
保存をすると、EMPからExpressionへのリンクにTransfarが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/804d1182-03f8-78d2-d63a-6f6556184816.png)
Transfarを選択すると、右側のプロパティでOptionの編集ができます。Credential nameがデフォルトではODIとなっているため、あらかじめ作成していた資格証明の名前に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/8d1b0050-285c-e772-9ed2-adc6204b6f42.png)

# 5.検証と実行
フローの作成が完了したので、保存をしてから、Validateで検証を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/cbdce5cc-7bf3-4dde-beaf-2a01c045317b.png)
検証が成功しましたら、Code Simulationで生成されるコードを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/59b59aa0-5a7c-21b9-f3c4-111ad82e3211.png)
内容を見てみると、次のような流れでした。
+ ステージングの表の作成、ターゲットの表を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/1a422376-ad15-9800-fd89-3b1febbda32e.png)
+ ファイルのURIを生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/48b6a241-5814-6de6-d11d-2face0bbaef5.png)
+ DBMS_CLOUD.COPY_DATAを使って、ステージングの表にデータをロード。TransfarのOptionはこちらで指定されるもののようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/12d66d52-5356-b4fa-24e1-0ca3943ce58b.png)
+ ステージング表からターゲット表へ挿入
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/903e4e3e-621d-8909-c497-f4ffaa00031d.png)
実行をしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/4484aaf0-413f-d73a-b7d1-73bfc14a0201.png)
ジョブの状況は、データ・フローの右側に表示がされます。Current StatusがrunningからDoneになり、成功しました。もしエラーになった場合は、Execution Jobに表示されているジョブのリンクをたどってエラーを確認して対応します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/e5c993ad-9713-a441-94c8-4b003e6acda2.png)
キャンバス上のFLOW_OUT1を選択して、Previewを確認すると、データが正しく挿入されていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/22663be5-53a8-6402-5140-1e8d28d1e125.png)

# おわりに
Data Transformsを使って、Object StorageのファイルをAutonomous Databaseに変換、結合して連携してみました。Object Storageをソースとして利用する場合は以下の注意がドキュメントにあります。

+ Oracle Object Storage接続を使用してデータをData Transformsにインポートするには、パブリックIPアドレスを使用して計算ノードにアクセスする必要があります。プライベート IP アドレスを使用して Object Storage サービスにアクセスする場合は、インターネットにアクセスできることを確認してください。
+ Oracle Object StorageからAutonomous Databaseへ、またはその逆にデータをロードするためにサポートされているファイル形式はCSVです。
+ サポートされているデータ型は、数値、倍精度浮動小数点型、文字列型、日付型です。
+ データ・ロードは、Oracle Object Storage接続ではサポートされていません。
Oracle Object Storage接続をマッピングのターゲットとして使用することはできません。
+ Oracle Object Storage接続を作成するには、Oracle Cloud Infrastructureユーザー名と認証トークンが必要です。認証トークンを生成する方法については、「認証トークンの取得」を参照してください。
+ Object StorageからAutonomous Databaseにデータをマップするデータ・フローを作成する場合はターゲット・スキーマに資格証明を作成する必要があります。

また2023/9に実行してみたところでは日本語は扱えませんでした。emp_jp.csvは日本語データが入ったファイルだったのですが、Previewで参照するとこちらのように表示がされません。
```
EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO
7839,中島 亜希子,社長,,81-11-17,5000,,10
7698,伊藤 明子,マネージャー,7839,81-05-01,2850,,30
7782,坂本 明,マネージャー,7839,81-06-09,2450,,10
7566,関口 晃,マネージャー,7839,81-04-02,2975,,20
7788,新井 敦子,アナリスト,7566,82-12-09,3000,,20
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/4042d806-0e54-de78-a485-6d2c3b168806.png)


外部表としてアクセスする場合は日本語も表示されたので、Database Actionsのデータロードのデータのリンクを利用して外部表を作成してからData Transformsで利用する、Data Transformsで完結したい場合は、PL/SQLを記述することができるWorkflowを利用するなどの対応が必要になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134317/0e40abad-7baf-9e3c-8750-50cbc27a945c.png)

# 参考資料
+ [Transform Data Using Data Studio](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/autonomous-data-transforms.html#GUID-CE0965B2-5F3C-4207-915F-B9BE15BEC135)
+ [403 : Data Transformsを使ってみよう](https://oracle-japan.github.io/ocitutorials/database/adb403-data-transforms/)
+ [102: ADBにデータをロードしよう(Database Actions)](https://oracle-japan.github.io/ocitutorials/database/adb102-dataload/)