Azure Data Factoryで取得したSalesforceデータにVantageでアクセスしてみた

とても多くのお客様がVantageとMicrosoft Azure First Party Servicesとの統合に関心を持っています。そのようなトピックからここではAzure BLOBとVantageの接続しAzure Data Factoryから取得したSalesforceデータをクエリする方法について説明します。

このガイドで説明するアプローチはVantageとAzure BLOBストレージとを統合するための多くの可能性のあるアプローチの一つであり、そのままの形で提供されるものです。 このアプローチは社内で実装されテストされていますが、TeradataまたはAzureのいずれからも、このアプローチに関する正式なサポートはありませんのでご注意ください。
ただしAzure Data FactoryはデータソースとしてSalesforceをサポートしています。

免責事項：本ガイドは、AzureとTeradata製品の両方のドキュメントからの内容を含んでいます。

# 概要

この記事ではSalesforceから顧客情報を取得しVantageからの注文および出荷情報と組み合わせてさらに分析を行うためのプロセスについて説明します。

Azure Data FactoryはSalesforceからAzure Blob Storageに顧客データを転送します。Teradata VantageはNative Object Store（NOS）機能を使用してBlob Storage上のデータとVantageのデータを1つのクエリで結合します。 
以下は、ワークフローの図です。

![画像1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/f4a633b8-7bfd-0015-6169-2e8e94c2701d.png)

# Azure Data Factoryについて

[Azure Data Factory](https://azure.microsoft.com/en-us/services/data-factory/#overview)はデータの移動をオーケストレーションしデータを大規模に変換するためのデータ駆動型ワークフローを作成できるクラウドベースのETLおよびデータ統合サービスです。
Azure Data Factoryを使用すると異種データストアからデータを取り込むことができるデータ駆動型ワークフロー（パイプラインと呼ばれる）を作成しスケジュールすることができます。

今日Azure Data FactoryはAzure Blob Storage、Teradata Vantage、Salesforce、Snowflakeを含むソースとシンクターゲットから選択する90以上の[コネクタ](https://docs.microsoft.com/en-us/azure/data-factory/copy-activity-overview)をサポートしています。
詳細については、[ドキュメント](https://docs.microsoft.com/en-us/azure/data-factory/)を参照してください。

# 前提条件

Azure Data Factory、Salesforce、Vantageに精通した方を想定しています。
以下のアカウント、システムが必要です。

- Azureサブスクリプションまたは[無料アカウント](https://azure.microsoft.com/free/)作成。
-[Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal)のアカウントとコンテナ。
- [Azure Data Factory](https://docs.microsoft.com/en-us/azure/data-factory/quickstart-create-data-factory-portal#create-a-data-factory)インスタンス
- SQLE 17.0+を搭載したTeradata Vantageインスタンス
- Salesforceのアカウント、または以下の要件を満たす開発者アカウントに[サインアップ](https://developer.salesforce.com/)してください。 
	- お客様の Salesforce アカウントで、API アクセスを有効にする必要があります。API アクセスは、Enterprise、Unlimited、Developer、および Performance の各エディションでデフォルトで有効になっています。
詳細については、[権限設定による Salesforce での API アクセスの有効化](https://www.data2crm.com/migration/faqs/enable-api-access-salesforce-permission-set/)を参照してください。

# 手順
前提条件を満たした上で、以下のステップを踏んでください。
1.	CopyDataパイプラインジョブを作成する
2.	NOSを使用してデータを探索する

# ステップ1 CopyDataパイプラインジョブを作成する
この手順ではAzure Data FactoryのCopy Dataツールを使用してSalesforceからAzure Blob Storageにデータをコピーする方法を概説します。この例ではSalesforceの開発者アカウントを使用してSalesforceに接続します。
詳細については、[Use the Copy Data tool to copy data](https://docs.microsoft.com/en-us/azure/data-factory/quickstart-create-data-factory-copy-data-tool)を参照してください。

**AzureデータファクトリのUIを公開**

[Azureポータル](https://portal.azure.com/)にログインしData Factoryインスタンスを開き「Author & Monitor」タイルを選択してAzure Data Factoryユーザーインターフェイス（UI）アプリケーションを別タブで起動します。

**データコピーツールを起動する**

1．データファクトリーページに切り替え、「Copy data」タイルを選択し「Copy data」ツールを起動します。

![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/e68b467f-0596-35ec-f0f2-0f53f68ea8d9.png)

2．Propatiesページで、パイプラインの名前とその説明を指定し「Next」をクリックします。

![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/cfb2b2fc-9814-14f2-dd1c-c1fc2a8c03f1.png)

3．Source Data Storeページで次の手順に従ってSalesforceソース接続を定義します。
a.	接続を追加するには「+Create new connection」をクリックします。

![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/8453f2d8-a022-f6c5-7045-98ba204b6d4e.png)

b.	ギャラリーから「Salesforce」を選択し「Continue」をクリックします。

![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/997cf560-5930-885b-c303-7187dd056a1a.png)

c.	New linked service(Salesforce)の設定を行います。
連携サービスのName、Environment url(例: https://login.salesforce.com)、Salesforceアクセス用のUser name、Password、Security tokenを入力し「Create」をクリックします。

![画像7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/a609f19e-e75f-3ed8-72fb-beb72e44bd5d.png)

セキュリティトークンの取得とリセットの方法については、[セキュリティトークンを取得する](https://help.salesforce.com/apex/HTViewHelpDoc?id=user_security_token.htm)を参照してください。
ヒント SalesforceにログインしてSalesforce Classicに切り替え、メニューバーのユーザ名ドロップダウンをクリックしてマイセッティングを選択し、左側のパーソナルフォルダを開いてセキュリティトークンのリセットを実行することでメールセキュリティトークンを受信できます。

詳細については、[Azure Data Factory を使用してSalesforceから、または Salesforceへデータをコピーする](https://docs.microsoft.com/en-us/azure/data-factory/connector-salesforce)を参照してください。

4．Source data storeページで、Salesforce1接続を選択し「Next」をクリックします。

![画像8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/c346dc58-4faf-52d5-7c92-7b251a083c3b.png)

5．次に、Existing Tablesオブジェクトを選択しAccountオブジェクトを選択し「Next」をクリックします。

![画像9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/d1938048-d139-0d47-3eed-d23375c16888.png)

6．Apply Filterページでデフォルトを選択し「Next」をクリックします。
7．Destination data storeページで、以下の手順に従って Azure Blob Storage のデスティネーション接続を定義する。
a. 「+ Create new connection」をクリックしNew linked serviceにAzure Blob Storage接続を追加し「Continue」をクリックします。

![画像10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/1fd0df20-77bc-d939-5e88-371c0cd147fe.png)

b. New Linked service（Azure Blob Storage）ページの設定を行います。Authentication method（例：アカウントキー）を入力し、Account Selection methodは [From Azure subscription] を選択し、Azure subscriptionとStorage account nameを入力し「Create」をクリックします。

![画像11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/038639df-485d-e6eb-08b6-a4390df23427.png)

8．Destination data storeページで新しいAzureBlobStorage1接続を選択し「Next」をクリックします。

![画像12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/6b6a1529-4a6e-c9cd-64d9-40dc5599e01f.png)

9．Choose the output file or folderページで次の手順を実行します。
a. BrowseをクリックしてBLOBストレージアカウントに作成したコンテナを選択し「Select」をクリックします。
b. File name（例：salesforce）を入力し「Next」をクリックします。

![画像13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/19a1d1ec-b3cb-5dc2-9e0d-c2ee37436e6e.png)

注：この記事ではパラメータ「最大同時接続数」と「ブロックサイズ」を評価していません。詳細については、[シンクタイプとしてのBlobストレージを参照](https://docs.microsoft.com/en-us/azure/data-factory/connector-azure-blob-storage#blob-storage-as-a-sink-type)してください。

10．File format settingsページで、出力ファイルのファイル形式設定（例：JSON）を行い「Next」を選択します。

![画像14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/76499b3d-41a4-5caa-758c-89b2bfd6583b.png)

注：Azure Blob Storageがサポートするファイル形式はText、Avro、ORC、JSON、Parquetです。詳細については、[シンクタイプとしてのBlobストレージ](https://docs.microsoft.com/en-us/azure/data-factory/connector-azure-blob-storage#blob-storage-as-a-sink-type)を参照してください。

VantageのNOS機能では外部ファイルはJSON、CSV、Parquetの各フォーマットに対応しており、アクセスに関するルールや要件があります。詳細については、[Teradata Vantage™ - Native Object Store Getting Started Guide Release](https://docs.teradata.com/search/books?query=Teradata+Vantage%25E2%2584%25A2+-+Native+Object+Store+Getting+Started+Guide&content-lang=en-US)を参照してください。

11．Schema mappingページですべての列を選択し「Next」をクリックします。

![画像15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/9e15bdba-97af-e798-803c-7476bade422b.png)

12．Settingページでデフォルトとする設定（例：空白）を選択し「Next」をクリックします。

![画像16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/220aa558-3fb9-67fd-9cb6-d49168d60541.png)

:::note
この記事では、以下の項目は評価していません：
- **Enable staging** - 中間ステージングストアを介してデータをコピーするかどうかを指定します。
- **データ統合ユニット** - コピー・エクゼキュータの強力さを指定します。値は2～256です。Auto」を選択するとこのData Factoryはソースとシンクのペアとデータパターンに基づいて最適なDIUの設定を動的に適用します。クリックすると詳細が表示されます。
-  **コピー並列化の度合い** - データ読み込みに使用する並列化の度合いを指定します。parallelCopiesプロパティはコピー・アクティビティで使用する並列処理を示します。このプロパティはコピー・アクティビティ内でソースからシンク・データストアに並行して読み込むことができるスレッドの最大数と考えることができます。
:::

ユーザーはコピー元、コピー先、クラウドエコシステムのインフラストラクチャに基づいて適切な設定を試す必要があります。詳しくは、[コピーパフォーマンス最適化機能](https://docs.microsoft.com/en-us/azure/data-factory/copy-activity-performance#copy-performance-optimization-features)をご覧ください。

13．Summaryページですべての設定を確認し「Next」を選択します。

![画像17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/41b33736-2aa0-ceda-f209-ae76b0b5a01e.png)

14．Deployment completeページで、「Monitor」をクリックしてジョブの進行状況を確認するかジョブが正常に完了した場合は「Finish」をクリックします。

![画像18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/041685cf-6826-a42b-d666-bec1d7a7bd3e.png)

# ステップ2. NOSを使ったデータの探索

Native Object StoreにはAzure Blob Storage内のデータを探索および分析するための機能が組み込まれています。ここではNOSのよく使われる機能をいくつか挙げています。

詳細な情報は**Native Object Store - Teradata Vantage Advance SQL Engine 17.0 (Orange Book)**　に記載されています。

### 1.外部テーブルの作成


外部テーブルを使用するとVantage SQL Engine内で外部データを簡単に参照でき構造化されたリレーショナル形式 でデータを利用できるようになります。

外部テーブルを作成するには、まず認証情報を使用してTeradata Vantageシステムにログインします。Blob Storageコンテナにアクセスするためのアクセスキーを持つAUTHORIZATIONオブジェクトを作成します。AuthorizationオブジェクトはAzure Blob Storageデータにアクセスするために誰が外部テーブルの使用を許可されるかの制御を確立することによってセキュリティを強化します。

```sql:create_autorization.sql
CREATE AUTHORIZATION DefAuth_AZ
AS DEFINER TRUSTED
USER 'mystor************'     /* storage account name */
PASSWORD '********';	         /* storage account access key or SAS Token */
```
USERはストレージアカウント名、PASSWORDはアクセスキーまたはSAS Tokenです。
Blob Storage上のJSONファイルに対して、以下のコマンドを使用して外部テーブルを作成します。

```sql:create_foreigntbl.sql
CREATE MULTISET FOREIGN TABLE salesforce,
EXTERNAL SECURITY DEFINER TRUSTED DefAuth_AZ
(
	Location VARCHAR(2048) CHARACTER SET UNICODE CASESPECIFIC,
	Payload JSON(8388096) INLINE LENGTH 32000 CHARACTER SET UNICODE 
)
USING
(
    LOCATION ('/AZ/mystor*****.blob.core.windows.net/data')
);
```

最低限、外部テーブル定義にはテーブル名とオブジェクトストアのデータを指すLocation句（黄色でハイライト）を含める必要があります。LocationにはAzure Blob Storage で「コンテナ」と呼ばれるトップレベルの単一名 (例: data) が必要です。

ファイル名の末尾に標準的な拡張子（.json、.csv、.parquet）がない場合データファイルのタイプを示すためにLocationおよびPayload列の定義も必要です。
また外部テーブルは常にNo Primary Index (NoPI)テーブルとして定義されます。

外部テーブルが作成されると外部テーブル上でSelect文を実行することによりBlob Storageデータセットの内容を照会することができます。

```sql:select_foreigntbl.sql
SELECT * FROM salesforce;
SELECT payload.* FROM salesforce;
```

外部テーブルには、2つのカラムしか含まれていません。LocationとPayloadです。Locationは、オブジェクトストアシステム内のアドレスです。データ自体はpayloadカラムで表され、外部テーブルの各レコード内のpayload値は、1つのJSONオブジェクトとそのすべての名前-値ペアを表します。

「SELECT * FROM salesforce;」の出力の一部です。

![画像19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/0f4a56f6-4edb-6243-6b8e-d95fb5aa7a01.png)

「SELECT payload.* FROM salesforce;」の出力の一部です。

![画像20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/b0e6851c-abca-4ae5-2f7e-da79c85c769b.png)

### 2.	JSON_KEYS 表演算子

JSON データはレコードによって異なる属性を含むことがあります。データストアで可能な属性の全リストを確認するには、JSON_KEYSを使用します：

```sql:select_jsonkey.sql

SELECT DISTINCT * FROM JSON_KEYS (ON (SELECT payload FROM salesforce)) AS j;
```
出力結果の一部です。

![画像21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/7230fc0f-72fa-f31e-0e84-d6b125a2aa22.png)

### 3.	ビューの作成

ビューはペイロード属性に関連する名前を単純化しオブジェクトストアのデータに対して実行可能なSQLを簡単にコーディングできるようにし、外部テーブルのLocation参照を隠して通常の列のように見えるようにすることができます。
以下は上記のJSON_KEYSテーブル演算子から検出された属性を使用したビュー作成文のサンプルです。

```sql:replace_view.sql
REPLACE VIEW salesforceView AS (
    SELECT CAST(payload.Id AS VARCHAR(20)) Customer_ID,
           CAST(payload."Name" AS VARCHAR(100)) Customer_Name,
           CAST(payload.AccountNumber AS VARCHAR(10)) Acct_Number,
              CAST(payload.BillingStreet AS VARCHAR(20)) Billing_Street,
           CAST(payload.BillingCity AS VARCHAR(20)) Billing_City,
           CAST(payload.BillingState AS VARCHAR(10)) Billing_State,
           CAST(payload.BillingPostalCode AS VARCHAR(5)) Billing_Post_Code,       
              CAST(payload.BillingCountry AS VARCHAR(20)) Billing_Country,
           CAST(payload.Phone AS VARCHAR(15)) Phone,    
           CAST(payload.Fax AS VARCHAR(15)) Fax,
           CAST(payload.ShippingStreet AS VARCHAR(20)) Shipping_Street,
           CAST(payload.ShippingCity AS VARCHAR(20)) Shipping_City,
           CAST(payload.ShippingState AS VARCHAR(10)) Shipping_State,
           CAST(payload.ShippingPostalCode AS VARCHAR(5)) Shipping_Post_Code,          
           CAST(payload.ShippingCountry AS VARCHAR(20)) Shipping_Country,
           CAST(payload.Industry AS VARCHAR(50)) Industry,    
           CAST(payload.Description AS VARCHAR(200)) Description,
           CAST(payload.NumberOfEmployees AS VARCHAR(10)) Num_Of_Employee,           
           CAST(payload.CustomerPriority__c AS VARCHAR(10)) Priority,
           CAST(payload.Rating AS VARCHAR(10)) Rating,           
		      CAST(payload.SLA__c AS VARCHAR(10)) SLA,
           CAST(payload.AnnualRevenue AS VARCHAR(10)) Annual_Revenue, 
           CAST(payload."Type" AS VARCHAR(20)) Customer_Type,
           CAST(payload.Website AS VARCHAR(100)) Customer_Website,
           CAST(payload.LastActivityDate AS VARCHAR(50)) Last_Activity_Date
    FROM salesforce);

SELECT * FROM salesforceView;
```

「SELECT * FROM salesforceView;」の出力結果の一部です。

![画像22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/82614bb1-b81b-506f-7fdc-582ae7c2e58f.png)

### 4.	READ_NOS 表演算子

READ_NOSテーブル演算子は最初に外部テーブルを定義することなくデータの一部をサンプリングして探索したりLocation句で指定したすべてのオブジェクトに関連するキーのリストを表示するために使用することができます。

```sql:select_usingreadNOS.sql
SELECT top 5 payload.*
FROM READ_NOS (
  ON (SELECT CAST(NULL AS JSON CHARACTER SET Unicode))
USING
   LOCATION   ('/AZ/mystor*****.blob.core.windows.net/data')
   ACCESS_ID ('mystor************')		/* storage account name */
   ACCESS_KEY (‘***********’)				/* storage account access key or SAS Token */
 ) AS D
GROUP BY 1;
```

出力結果の一部を示します。

![画像23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/2fdcc47e-f4d4-6087-61b3-a119a604035b.png)

### 5.	Blob Storage データとデータベース内テーブルの結合

外部テーブルはVantage のテーブルと結合してさらに分析することができます。たとえば、注文情報はVantageのOrders、Order_Items、Shipping_Addressという3つのテーブルに格納されています。

Orders の DDL：

```sql:create_oders.sql
CREATE TABLE Orders (
	Order_ID INT NOT NULL,
	Customer_ID VARCHAR(20) CHARACTER SET LATIN CASESPECIFIC,
	Order_Status INT,
	-- Order status: 1 = Pending; 2 = Processing; 3 = Rejected; 4 = Completed
	Order_Date DATE NOT NULL,
	Required_Date DATE NOT NULL,
	Shipped_Date DATE,
	Store_ID INT NOT NULL,
	Staff_ID INT NOT NULL
) Primary Index (Order_ID);
```

Order_ItemsのDDL：

```sql:create_orderitems.sql
CREATE TABLE Order_Items(
	Order_ID INT NOT NULL,
	Item_ID INT,
	Product_ID INT NOT NULL,
	Quantity INT NOT NULL,
	List_Price DECIMAL (10, 2) NOT NULL,
	Discount DECIMAL (4, 2) NOT NULL DEFAULT 0
) Primary Index (Order_ID, Item_ID);
```

Shipping_AddressのDDL：

```sql:create_shippingaddress.sql
 CREATE TABLE Shipping_Address (
	Customer_ID VARCHAR(20) CHARACTER SET LATIN CASESPECIFIC NOT NULL,
	Street VARCHAR(100) CHARACTER SET LATIN CASESPECIFIC,
	City VARCHAR(20) CHARACTER SET LATIN CASESPECIFIC,
	State VARCHAR(15) CHARACTER SET LATIN CASESPECIFIC,
	Postal_Code VARCHAR(10) CHARACTER SET LATIN CASESPECIFIC,
	Country VARCHAR(20) CHARACTER SET LATIN CASESPECIFIC
) Primary Index (Customer_ID);
```

また、テーブルには以下のデータとします。

Orders：
![画像24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/877aebcf-5391-6751-de14-f2b52b6e1780.png)

Order_Items：
![画像25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/805bf3e9-7acb-d3ed-82b4-4ca4a7225452.png)

Shipping_Address：
![画像26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/ed123367-c80c-4819-c21b-8e80e0a3eabc.png)

データベースで確立されたテーブルOrdersとOrder_Itemsにsalesforceの外部テーブルを結合することで顧客の注文情報を顧客の連絡先とともに取得することができるのです。

```sql:select_withjoin.sql
SELECT s.payload.Id as Customer_ID, 
       s.payload."Name" as Customer_Name,
       s.payload.AccountNumber as Acct_Number,
       o.Order_ID as Order_ID,
       o.Order_Status as Order_Status,
       o.Order_Date as Order_Date,
       oi.Item_ID as Item_ID,
       oi.Product_ID as Product_ID,
       sa.Street as Shipping_Street,
       sa.City as Shipping_City,
       sa.State as Shipping_State,
       sa.Postal_Code as Shipping_Postal_Code,
       sa.Country as Shipping_Country
FROM salesforce s, Orders o, Order_Items oi, Shipping_Address sa
WHERE s.payload.Id = o.Customer_ID
AND o.Customer_ID = sa.Customer_ID
AND o.Order_ID = oi.Order_ID
ORDER BY 1;
```

出力結果の一部を示します。

![画像27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/3c5b8980-e02d-93f7-bef5-bf43bc8faf3d.png)

### 6.	Blob StorageデータをVantageにインポートする

Blob Storageデータの永続的なコピーを持つことは同じデータへの繰り返しアクセスが予想される場合に便利です。NOSの外部テーブルは自動的にBlob Storageデータの永続的なコピーを作成するわけではありません。

データベース内にデータを取り込むためのいくつかのアプローチを以下に説明します：

**データ付きテーブルを作成する**

CREATE TABLE AS ... WITH DATA" ステートメントは外部テーブル定義がソーステーブルとして機能する状態で使用することができます。この方法では、外部テーブルのペイロードの中からターゲットテーブルに含める属性を選択し、リレーショナルテーブルのカラムにどのような名前を付けるかを決定します。

```sql:create_AsWithData.sql
CREATE TABLE salesforceVantage AS (
     SELECT   CAST(payload.Id AS VARCHAR(20)) Customer_ID,
           CAST(payload."Name" AS VARCHAR(100)) Customer_Name,
              CAST(payload.AccountNumber AS VARCHAR(10)) Acct_Number,
           CAST(payload.BillingStreet AS VARCHAR(20)) Billing_Street,
           CAST(payload.BillingCity AS VARCHAR(20)) Billing_City,
           CAST(payload.BillingState AS VARCHAR(10)) Billing_State,
           CAST(payload.BillingPostalCode AS VARCHAR(5)) Billing_Post_Code,       
           CAST(payload.BillingCountry AS VARCHAR(20)) Billing_Country,
           CAST(payload.Phone AS VARCHAR(15)) Phone,    
           CAST(payload.Fax AS VARCHAR(15)) Fax,
           CAST(payload.ShippingStreet AS VARCHAR(20)) Shipping_Street,
           CAST(payload.ShippingCity AS VARCHAR(20)) Shipping_City,
           CAST(payload.ShippingState AS VARCHAR(10)) Shipping_State,
           CAST(payload.ShippingPostalCode AS VARCHAR(5)) Shipping_Post_Code,          
           CAST(payload.ShippingCountry AS VARCHAR(20)) Shipping_Country,
           CAST(payload.Industry AS VARCHAR(50)) Industry,    
           CAST(payload.Description AS VARCHAR(200)) Description,
           CAST(payload.NumberOfEmployees AS INT) Num_Of_Employee,           
           CAST(payload.CustomerPriority__c AS VARCHAR(10)) Priority,
           CAST(payload.Rating AS VARCHAR(10)) Rating,           
		            CAST(payload.SLA__c AS VARCHAR(10)) SLA,
           CAST(payload."Type" AS VARCHAR(20)) Customer_Type,
           CAST(payload.Website AS VARCHAR(100)) Customer_Website,
           CAST(payload.AnnualRevenue AS VARCHAR(10)) Annual_Revenue,
           CAST(payload.LastActivityDate AS DATE) Last_Activity_Date
     FROM salesforce)
WITH DATA
NO PRIMARY INDEX;

SELECT * FROM salesforceVantage;
```

「SELECT * FROM salesforceVantage;」の出力結果の一部です。

![画像28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/dbd1f47d-c178-b256-9049-7961c7b2db4d.png)

外部テーブルを使用する代わりにREAD_NOSテーブル演算子を使用することもできます。このテーブル演算子により最初に外部テーブルを構築することなくオブジェクトストアから直接データにアクセスすることができます。READ_NOSをCREATE TABLE AS句と組み合わせて、データベース内にデータの永続的なバージョンを構築することができます。

```sql:create_AsWithDatausingReadNOS.sql
CREATE TABLE salesforceReadNOS AS (
     SELECT  CAST(payload.Id AS VARCHAR(20)) Customer_ID,
           CAST(payload."Name" AS VARCHAR(100)) Customer_Name,
           CAST(payload.AccountNumber AS VARCHAR(10)) Acct_Number,
           CAST(payload.BillingStreet AS VARCHAR(20)) Billing_Street,
           CAST(payload.BillingCity AS VARCHAR(20)) Billing_City,
           CAST(payload.BillingState AS VARCHAR(10)) Billing_State,
           CAST(payload.BillingPostalCode AS VARCHAR(5)) Billing_Post_Code,       
           CAST(payload.BillingCountry AS VARCHAR(20)) Billing_Country,
           CAST(payload.Phone AS VARCHAR(15)) Phone,    
           CAST(payload.Fax AS VARCHAR(15)) Fax,
           CAST(payload.ShippingStreet AS VARCHAR(20)) Shipping_Street,
           CAST(payload.ShippingCity AS VARCHAR(20)) Shipping_City,
           CAST(payload.ShippingState AS VARCHAR(10)) Shipping_State,
           CAST(payload.ShippingPostalCode AS VARCHAR(5)) Shipping_Post_Code,          
           CAST(payload.ShippingCountry AS VARCHAR(20)) Shipping_Country,
           CAST(payload.Industry AS VARCHAR(50)) Industry,    
        CAST(payload.Description AS VARCHAR(200)) Description,
        CAST(payload.NumberOfEmployees AS INT) Num_Of_Employee,           
        CAST(payload.CustomerPriority__c AS VARCHAR(10)) Priority,
             CAST(payload.Rating AS VARCHAR(10)) Rating,           
                             CAST(payload.SLA__c AS VARCHAR(10)) SLA,
        CAST(payload."Type" AS VARCHAR(20)) Customer_Type,
        CAST(payload.Website AS VARCHAR(100)) Customer_Website,
        CAST(payload.AnnualRevenue AS VARCHAR(10)) Annual_Revenue,
             CAST(payload.LastActivityDate AS DATE) Last_Activity_Date
FROM READ_NOS (
  ON (SELECT CAST(NULL AS JSON CHARACTER SET Unicode))
USING
   LOCATION   ('/AZ/mystor*****.blob.core.windows.net/data')
   ACCESS_ID ('mystor************')/*storage account name*/
   ACCESS_KEY (‘***********’)		 /*storage account access key or SAS Token*/
 ) AS D
) WITH DATA;

SELECT * FROM salesforceReadNOS; 
```

「SELECT * FROM salesforceReadNOS;」の出力結果の一部です：

![画像29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/3f2a2ab3-efbb-f709-bbe4-f20d5909934d.png)

**INSERT SELECTステートメント**

Blob Storageデータをリレーショナルテーブルに配置するもう1つの方法は"INSERT SELECT"によるものです。この方法では外部テーブルがソーステーブルとなり新しく作成されたパーマネントテーブルが挿入されるテーブルとなります。上記のREAD_NOSの例とは逆にこの方法では永続テーブルを事前に作成する必要があります。

INSERT SELECT方式の利点の1つはターゲット・テーブルの属性を変更できることです。例えばターゲットテーブルをMULTISETにするかしないかを指定したり別のプライマリインデックスを選択したりすることができます。

```sql:create_insertselect.sql
CREATE TABLE salesforcePerm, FALLBACK ,
     NO BEFORE JOURNAL,
     NO AFTER JOURNAL,
     CHECKSUM = DEFAULT,
     DEFAULT MERGEBLOCKRATIO,
     MAP = TD_MAP1   
(
    Customer_Id VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Customer_Name VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
    Acct_Number VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Billing_Street VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Billing_City VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Billing_State VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Billing_Post_Code VARCHAR(5) CHARACTER SET LATIN NOT CASESPECIFIC,       
    Billing_Country VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Phone VARCHAR(15) CHARACTER SET LATIN NOT CASESPECIFIC,   
    Fax VARCHAR(15) CHARACTER SET LATIN NOT CASESPECIFIC,
    Shipping_Street VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Shipping_City VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Shipping_State VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Shipping_Post_Code VARCHAR(5) CHARACTER SET LATIN NOT CASESPECIFIC,       
    Shipping_Country VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Industry VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC,    
    Description VARCHAR(200) CHARACTER SET LATIN NOT CASESPECIFIC,
    Num_Of_Employee INT,           
    Priority VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Rating VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,           
	 SLA VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Customer_Type VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
    Customer_Website VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
    Annual_Revenue VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
    Last_Activity_Date DATE
) PRIMARY INDEX (Customer_ID); 

INSERT INTO salesforcePerm
     SELECT  CAST(payload.Id AS VARCHAR(20)) Customer_ID,
             CAST(payload."Name" AS VARCHAR(100)) Customer_Name,
             CAST(payload.AccountNumber AS VARCHAR(10)) Acct_Number,
             CAST(payload.BillingStreet AS VARCHAR(20)) Billing_Street,
             CAST(payload.BillingCity AS VARCHAR(20)) Billing_City,
             CAST(payload.BillingState AS VARCHAR(10)) Billing_State,
             CAST(payload.BillingPostalCode AS VARCHAR(5)) Billing_Post_Code,       
             CAST(payload.BillingCountry AS VARCHAR(20)) Billing_Country,
             CAST(payload.Phone AS VARCHAR(15)) Phone,    
             CAST(payload.Fax AS VARCHAR(15)) Fax,
             CAST(payload.ShippingStreet AS VARCHAR(20)) Shipping_Street,
             CAST(payload.ShippingCity AS VARCHAR(20)) Shipping_City,
             CAST(payload.ShippingState AS VARCHAR(10)) Shipping_State,
             CAST(payload.ShippingPostalCode AS VARCHAR(5)) Shipping_Post_Code,          
             CAST(payload.ShippingCountry AS VARCHAR(20)) Shipping_Country,
             CAST(payload.Industry AS VARCHAR(50)) Industry,    
             CAST(payload.Description AS VARCHAR(200)) Description,
             CAST(payload.NumberOfEmployees AS INT) Num_Of_Employee,           
             CAST(payload.CustomerPriority__c AS VARCHAR(10)) Priority,
             CAST(payload.Rating AS VARCHAR(10)) Rating,           
                            CAST(payload.SLA__c AS VARCHAR(10)) SLA,
             CAST(payload."Type" AS VARCHAR(20)) Customer_Type,
             CAST(payload.Website AS VARCHAR(100)) Customer_Website,
             CAST(payload.AnnualRevenue AS VARCHAR(10)) Annual_Revenue,
             CAST(payload.LastActivityDate AS DATE) Last_Activity_Date
FROM salesforce;

SELECT * FROM salesforcePerm;
```

「SELECT * FROM salesforcePerm;」の出力結果の一部です。

![画像30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/cc070cc8-c319-7d1c-b1cc-6df78a9414ad.png)

詳細については、[Teradata Vantage™ - Native Object Store Getting Started Guide](https://docs.teradata.com/search/books?query=Teradata+Vantage%25E2%2584%25A2+-+Native+Object+Store+Getting+Started+Guide&content-lang=en-US)を参照してください。

# おわりに
Azure BLOB Storageを利用したSalesforceデータの活用はいかがでしたでしょうか？
ぜひお試しください！

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)