Amazon Appflowを使用してVantageからSalesforceへ接続する方法

著者 [Wenjie Tehan](wenjie.tehan@teradata.com)
最終更新日 2022年2月14日

:::note warn
警告
本記事は[Getting Started](https://quickstarts.teradata.com/index.html#getting-access-to-vantage)に掲載された内容を抄訳したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

# 概要
このハウツーでは、SalesforceとTeradata Vantageの間でデータを移行するプロセスについて説明します。2つのユースケースを含みます。

①	Salesforceから顧客情報を取得し、Vantageから注文および出荷情報と組み合わせて、分析的な洞察を得ます。

②	Vantage の **newleads** テーブルを Salesforce のデータで更新し、AppFlow を使用して新しいリードを Salesforce に追加します。
![画像01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/acee6e0d-8069-28e9-fc20-94bfa83fc56c.png)


Amazon AppFlowは、SalesforceからAmazon S3に顧客アカウントデータを転送します。その後、Vantage は Native Object Store (NOS) の読み込み機能を使用して、Amazon S3 のデータと Vantage のデータを 1 回のクエリで結合します。

アカウント情報は、Vantage 上の **newleads** テーブルの更新に使用されます。テーブルが更新されると、VantageはNOS WriteでAmazon S3バケットに書き戻す。新しいリードデータファイルの到着時にLambda関数が起動し、データファイルをParquet形式からCSV形式に変換し、AppFlowは新しいリードをSalesforceに挿入し直します。



# Amazon AppFlowについて
Amazon AppFlowは、Salesforce、Marketo、Slack、ServiceNowなどのSaaSアプリケーションと、Amazon S3やAmazon RedshiftなどのAWSサービス間で安全にデータを転送できる、フルマネージド型の統合サービスです。AppFlowは、移動中のデータを自動的に暗号化し、AWS PrivateLinkと統合されたSaaSアプリケーションの公衆インターネット上でのデータの流れを制限することができ、セキュリティ脅威への露出を減らすことができます。

本日現在、Amazon AppFlowは16のソースから選択でき、4つの宛先にデータを送信することができます。

# Teradata Vantageについて
Teradata Vantageは、エンタープライズ分析のためのマルチクラウド対応データプラットフォームであり、データに関する課題を最初から最後まで解決します。

Vantageにより、企業は小規模から始めてコンピュートやストレージを弾力的に拡張し、使用した分だけ支払い、低コストのオブジェクトストアを活用し、分析ワークロードを統合することができます。Vantageは、R、Python、Teradata Studio、その他あらゆるSQLベースのツールをサポートします。

Vantageは、記述的分析、予測的分析、処方的分析、自律的意思決定、ML機能、可視化ツールを統合したプラットフォームで、データがどこにあっても、リアルタイムのビジネスインテリジェンスを大規模に発掘することができます。


Teradata Vantage Native Object Store（NOS）は、Amazon S3などの外部オブジェクトストアにあるデータを、標準SQLを使用して探索することが可能です。NOSを使用するために、特別なオブジェクトストレージ側の計算インフラは必要ありません。Amazon S3のバケットにあるデータを探索するには、バケットを指すNOSテーブル定義を作成するだけでよいのです。NOSを使用すると、Amazon S3からデータを迅速にインポートしたり、Vantageデータベースの他のテーブルと結合したりすることもできます。


# 前提条件
Amazon AppFlowサービスおよびTeradata Vantageに精通していることが前提です。

以下のアカウントとシステムが必要です。

・Teradata Vantageインスタンスへのアクセス。

::: note info
メモ！
Vantageの新しいインスタンスが必要な場合は、[Google Cloud](https://quickstarts.teradata.com/vantage.express.gcp.html)、[Azure](https://quickstarts.teradata.com/run-vantage-express-on-microsoft-azure.html)、[AWS](https://quickstarts.teradata.com/run-vantage-express-on-aws.html)のクラウドにVantage Expressという無料版をインストールすることができます。また、[VMware](https://quickstarts.teradata.com/getting.started.vmware.html)、[VirtualBox](https://quickstarts.teradata.com/getting.started.vbox.html)、または[UTM](https://quickstarts.teradata.com/getting.started.utm.html)を使用して、ローカルマシン上でVantage Expressを実行することもできます。
:::

・フローの作成と実行が可能なロールを持つAWSアカウント。
・Salesforce データを保存するための Amazon S3 バケット (例: ptctsoutput)
・生の Vantage データ (Parquet ファイル) を保存する Amazon S3 バケット (例: vantageparquet)。このバケットには、Amazon AppFlowのアクセスを許可するポリシーが必要です。
・変換された Vantage データ (CSV ファイル) を保存する Amazon S3 バケット (例: vantagecsv)
・以下の要件を満たすSalesforceアカウント。

○　お客様の Salesforce アカウントで、API アクセスを有効にする必要があります。Enterprise、Unlimited、Developer、および Performance エディションでは、API アクセスはデフォルトで有効になっています。
○　Salesforce アカウントで、接続アプリのインストールが許可されている必要があります。これが無効になっている場合は、Salesforce 管理者にお問い合わせください。Amazon AppFlow で Salesforce 接続を作成した後、「Amazon AppFlow Embedded Login App」という名前の接続アプリが Salesforce アカウントにインストールされていることを確認します。
○　Amazon AppFlow Embedded Login App」のリフレッシュトークンポリシーは、「Refresh token is valid until revoked」に設定されている必要があります。そうでない場合、リフレッシュトークンの有効期限が切れるとフローが失敗します。
○　イベント駆動型のフロートリガーを使用するには、SalesforceのChange Data Captureを有効にする必要があります。セットアップから、クイック検索に「Change Data Capture」と入力します。
○　Salesforce アプリが IP アドレスの制限を実施している場合、Amazon AppFlow で使用するアドレスをホワイトリストに登録する必要があります。詳細については、Amazon Web Services General Reference の https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html[AWS IP address ranges] を参照してください。
○　Salesforce のレコードを 100 万件以上転送する場合、Salesforce の複合フィールドを選択することはできません。Amazon AppFlow は転送に Salesforce Bulk API を使用するため、複合フィールドの転送は許可されません。
○　AWS PrivateLinkを使用してプライベート接続を作成するには、Salesforceアカウントで「メタデータの管理」と「外部接続の管理」の両方のユーザー権限を有効にする必要があります。プライベート接続は現在、us-east-1 および us-west-2 の AWS リージョンで利用可能です。
○　履歴オブジェクトなど、更新できないSalesforceオブジェクトがあります。これらのオブジェクトについて、Amazon AppFlowは、スケジュールトリガー型のフローの増分エクスポート（「新しいデータのみを転送」オプション）をサポートしません。代わりに、「すべてのデータを転送する」オプションを選択し、適切なフィルタを選択して転送するレコードを制限することができます。

# 手順
前提条件を満たした上で、以下の手順で行います。

①	SalesforceからAmazon S3へのフローを作成する
②	NOSを使用してデータを探索する
③	NOS を使用して Vantage データを Amazon S3 にエクスポートします。
④	Amazon S3からSalesforceへのフローを作成する

# SalesforceからAmazon S3へのフローを作成する
このステップでは、Amazon AppFlowを使用してフローを作成します。この例では、[Salesforceの開発者アカウント](https://developer.salesforce.com/signup)を使用してSalesforceに接続します。

[AppFlowコンソール](https://console.aws.amazon.com/appflow)にアクセスし、AWSログイン認証でサインインし、**Create flow**をクリックします。正しいリージョンにいること、Salesforceのデータを保存するためのバケットが作成されていることを確認します。
![画像02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/690d1527-7010-8e29-d3bc-e6e17411dbad.png)

# ステップ1：フローの詳細を指定する
このステップでは、フローの基本情報を提供します。

**フロー名**（例：salesforce）と **フローの説明（オプション）** を入力し、**暗号化設定のカスタマイズ（詳細）** のチェックを外したままにします。**次へ**をクリックします。

# ステップ2：フローを設定する

このステップでは、フローのソースとデスティネーションに関する情報を提供します。この例では、ソースとして**Salesforce**を、デスティネーションとして**Amazon S3**を使用します。

・**Source name**でSalesforceを選択し、**Choose Salesforce connection**で**Create new connection**を選択します。
![画像03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/03d339b7-df4c-c1d9-757b-141698c90797.png)

・**Salesforce 環境**と**データの暗号化**には、デフォルトを使用します。接続に名前（例：salesforce）を付けて、[**続行**]をクリックします。
![画像04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/76b26d4f-5936-ff44-3bd1-78a8fd03c1a0.png)

・salesforceのログイン画面で、**Username**と**Password**を入力します。**ログイン**をクリックします。
![画像05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/e16ceb9a-48f2-0e3e-ec78-6aa86e4f0412.png)

・**許可**をクリックして、AppFlowによるSalesforceのデータおよび情報へのアクセスを許可します。
![画像06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/c8b5b200-0692-3a18-430f-d17ba9016606.png)


・AppFlowの**Configureフロー**ウィンドウに戻り、**Salesforceオブジェクト**を使用し、SalesforceオブジェクトとしてAccountを選択します。
![画像07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/f299c619-cce6-13ad-ccc5-01742e5f96e8.png)
![画像08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/ab1f82e6-fb96-b1a1-bcb9-6fcf40363058.png)

・**Destination name**としてAmazon S3を使用します。[先ほど](https://quickstarts.teradata.com/cloud-guides/integrate-teradata-vantage-to-salesforce-using-amazon-appflow.html#prerequisites)作成した、データを保存するバケットを選ぶ（例：ptctsoutput)
![画像09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/0b0e7fa5-6c28-14fb-07d5-9a9b8cac890b.png)

・**フロートリガー**を「オンデマンドで実行」にします。**Next**をクリックします。
![画像10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/2faed3d4-e2aa-9249-ef74-a5f2099260fd.png)

# ステップ3：データフィールドのマッピング
このステップでは、データがソースからデスティネーションに転送される方法を決定します。

・**マッピング方法**として、手動でフィールドをマッピングするを使用する。
・簡単のため、**送信元から送信先へのマッピング**は、すべてのフィールドを直接マッピングするを選択します。
![画像11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/3f4b021a-f13f-d232-100d-0bad07286a59.png)

「すべてのフィールドを直接マッピングする」をクリックすると、すべてのフィールドが「**マッピングされたフィールド**」の下に表示されます。**式の追加（連結）**、**値の修正（フィールド値のマスクまたは切り捨て）**、**選択したマッピングの削除**を行いたいフィールドのチェックボックスをクリックします。

この例では、チェックボックスはチェックされません。

・**バリデーション**では、「請求先住所」が含まれていないレコードを無視する条件を追加します（オプション）。**[次へ]**をクリックします。
![画像12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/837f9330-3182-836f-0e11-210b697de3bc.png)

# ステップ4：フィルタの追加
転送するレコードを決定するためのフィルタを指定することができます。この例では、削除されたレコードをフィルタリングする条件を追加します（オプション）。[**次へ**]をクリックします
![画像13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/1d04aab6-9cea-90f0-2aaf-50a456ed6a0c.png)

# ステップ5. レビューと作成
入力した情報をすべて確認します。必要であれば修正します。[**フローの作成**］をクリックします。

フローが作成されると、フロー情報とともにフロー作成成功のメッセージが表示されます。
![画像14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/e08c3e1c-ec59-0544-43d9-dfe21847983b.png)

# フローの実行
右上の**Run flow**をクリックします。

フローの実行が完了すると、実行が成功したことを示すメッセージが表示されます。

メッセージの例
![画像15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/439cdb18-ef65-bf05-6581-4cfd440803ef.png)

バケツのリンクをクリックすると、データが表示されます。Salesforce のデータは JSON 形式になります。

# データファイルのプロパティを変更する

デフォルトでは、Salesforceのデータは暗号化されています。NOSがアクセスするためには、暗号化を解除する必要があります。

Amazon S3バケット内のデータファイルをクリックし、「**プロパティ**」タブをクリックします。
![画像16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/1a2fd25f-6d13-25df-a6d5-3e0f9d26a286.png)

**Encryption** から AWS-KMS をクリックし、AWS-KMS encryption から None に変更します。[**保存**]をクリックします。
![画像17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/d53c0d0a-68be-578e-bb62-a74d4ccda863.png)

# NOSを使ったデータの探索
Native Object Storeには、Amazon S3内のデータを探索・分析するための機能が組み込まれています。ここでは、NOSのよく使われる機能をいくつか列挙します。

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

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

```:aaa
CREATE AUTHORIZATION DefAuth_S3
AS DEFINER TRUSTED
USER 'A*****************' /* AccessKeyId */
PASSWORD '********'; /* SecretAccessKey */
```

「USER "はAWSアカウントのAccessKeyId、"PASSWORD "はSecretAccessKeyです。

Amazon S3上のJSONファイルに対して、以下のコマンドで外部テーブルを作成します。

```:aaa
CREATE MULTISET FOREIGN TABLE salesforce,
EXTERNAL SECURITY DEFINER TRUSTED DefAuth_S3
(
  Location VARCHAR(2048) CHARACTER SET UNICODE CASESPECIFIC,
  Payload JSON(8388096) INLINE LENGTH 32000 CHARACTER SET UNICODE
)
USING
(
  LOCATION ('/S3/s3.amazonaws.com/ptctstoutput/salesforce/1ce190bc-25a9-4493-99ad-7497b497a0d0/903790813-2020-08-21T21:02:25')
);
```

最低限、外部テーブルの定義には、テーブル名と、オブジェクトストアのデータを指すLocation句（黄色でハイライトされています）を含める必要があります。ロケーションは、Amazonでは "バケット "と呼ばれるトップレベルの単一名が必要です。

ファイル名の末尾に標準的な拡張子（.json, .csv, .parquet）がない場合、データファイルの種類を示すために、LocationとPayload列の定義も必要です（ターコイズ色でハイライトされている）。

外部テーブルは常にNo Primary Index (NoPI)テーブルとして定義される。

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

```:aaa
SELECT * FROM salesforce;
SELECT payload.* FROM salesforce;
```


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

SELECT * FROM salesforce;」からの出力例。
![画像18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/9d36327a-dd72-6036-7413-2815062746f0.png)

サンプル出力形式「SELECT payload.* FROM salesforce;」。
![画像19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/96284b7c-d7dc-d469-74be-cc5adee17b5a.png)

# JSON_KEYS テーブル演算子
JSONデータには、レコードごとに異なる属性が含まれることがあります。データストアに含まれる可能性のある属性の完全なリストを決定するには、JSON_KEYSを使用します。

```:aaa
|SELECT DISTINCT * FROM JSON_KEYS (ON (SELECT payload FROM salesforce)) AS j;
```

このSQLの結果はとても大きいので一部のみの結果を示します。
![画像20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/93c0f060-abeb-4aa9-dda7-a085016136af.png)

# ビューの作成
ビューは、ペイロード属性に関連する名前を単純化し、オブジェクトストアのデータに対して実行可能なSQLを簡単にコーディングできるようにし、外部テーブルのLocation参照を隠して通常の列のように見えるようにすることができます。

以下は、上記の JSON_KEYS テーブル演算子から検出された属性を使用したビュー作成文のサンプルです。

```:aaa
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
);
```

```:aaa
SELECT * FROM salesforceView;
```

部分的に出力
![画像21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/a637bc66-d747-eb87-5fb6-1a1fccac239c.png)



# READ_NOSテーブル演算子

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

```:aaa
SELECT top 5 payload.*
FROM READ_NOS (
 ON (SELECT CAST(NULL AS JSON CHARACTER SET Unicode))
USING
LOCATION ('/S3/s3.amazonaws.com/ptctstoutput/salesforce/1ce190bc-25a9-4493-99ad-7497b497a0d0/903790813-2020-08-21T21:02:25')
 ACCESS_ID ('A**********') /* AccessKeyId */
 ACCESS_KEY ('***********') /* SecretAccessKey */
 ) AS D
GROUP BY 1;
```

出力します
![画像22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/33272e50-1472-e90a-7e15-c981ab249667.png)

# Amazon S3 データとデータベース内テーブルの結合

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

Orders の DDL

```:aaa
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

```:aaa
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です。

```:aaa
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);
```

また、テーブルには以下のデータがあります。

オーダー
![画像23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/cc925f7b-721b-258a-5806-8a2d926c37d7.png)

オーダー_アイテム
![画像24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/543065e9-79cc-e64e-dfde-b55d8ed897da.png)

Shipping_Address
![画像25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/e68605b3-ccc0-f79e-7ca2-52085a3dacf1.png)

データベースのOrders, Order_Items, Shipping_Address テーブルにsalesforceの外部テーブルを結合することで、顧客の注文情報を顧客の配送情報とともに取得することができます。

```:aaa
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;
```

結果
![画像26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/a7cdaa95-abbc-1524-2a95-82b2a423c4a1.png)

# Amazon S3 データを Vantage にインポートする

Amazon S3データの永続的なコピーを持つことは、同じデータへの反復的なアクセスが予想される場合に便利です。NOSの外部テーブルでは、自動的にAmazon S3データの永続的なコピーを作成しません。データベースにデータを取り込むためのいくつかのアプローチについて、以下に説明します。

CREATE TABLE AS ... WITH DATA "ステートメントは、ソーステーブルとして機能する外部テーブル定義で使用することができます。このアプローチでは、外部テーブルのペイロードのうち、ターゲットテーブルに含めたい属性と、リレーショナルテーブルのカラムの名前を選択的に選択することができます。

```:aaa
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** ; 部分的な結果。
![画像27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/199848f5-e032-e407-7e21-d6a1d547f150.png)


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

```:aaa
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 ('/S3/s3.amazonaws.com/ptctstoutput/salesforce/1ce190bc-25a9-4493-99ad-7497b497a0d0/903790813-2020-08-21T21:02:25')
      ACCESS_ID ('A**********') /* AccessKeyId */
      ACCESS_KEY ('***********') /* SecretAccessKey */
  ) AS D
) WITH DATA;
```

**salesforceReadNOS**テーブルの結果
```:aaa
SELECT * FROM salesforceReadNOS;
```
![画像28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/d4435738-6b7b-238a-d7d4-228adef70c97.png)

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

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

```:aaa
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);
```

```:aaa
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;
```

```:aaa
SELECT * FROM salesforcePerm;
```


サンプル結果です。
![画像29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/33b7a51d-2f7c-fa6d-c391-46bb54dcaa74.png)

# NOS を使用して Vantage データを Amazon S3 にエクスポートする

Vantageシステムで1行の**newleads**テーブルを持っています。
![画像30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/21b4ee5c-0768-ed6c-d7e2-cfc6a89eb413.png)

このリードには住所情報がないことに注意してください。Salesforceから取得したアカウント情報を使って、**newleads**テーブルを更新してみましょう。

```:aaa
UPDATE nl
FROM
  newleads AS nl,
  salesforceReadNOS AS srn
SET
  Street = srn.Billing_Street,
  City = srn.Billing_City,
  State = srn.Billing_State,
  Post_Code = srn.Billing_Post_Code,
  Country = srn.Billing_Country
  WHERE Account_ID = srn.Acct_Number;
```

これで、新しいリードにアドレス情報が付与されました。
![画像31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/9c720bc4-31b5-9880-59d2-ec883fc618ef.png)

WRITE_NOSを使用して、新しいリード情報をS3バケットに書き込む。

```:aaa
SELECT * FROM WRITE_NOS (
ON (
  SELECT
    Account_ID,
    Last_Name,
    First_Name,
    Company,
    Cust_Title,
    Email,
    Status,
    Owner_ID,
    Street,
    City,
    State,
    Post_Code,
    Country
  FROM newleads
)
USING
  LOCATION ('/s3/vantageparquet.s3.amazonaws.com/')
  AUTHORIZATION ('{"Access_ID":"A*****","Access_Key":"*****"}')
  COMPRESSION ('SNAPPY')
  NAMING ('DISCRETE')
  INCLUDE_ORDERING ('FALSE')
  STOREDAS ('CSV')
) AS d;
```
Access_IDはAccessKeyID、Access_KeyはBucketに対するSecretAccessKeyです。

# Amazon S3からSalesforceへのフローを作成する

ステップ1を繰り返し、ソースにAmazon S3、デスティネーションにSalesforceを使用したフローを作成します。

# ステップ1. フローの詳細を指定する

このステップでは、フローの基本情報を提供します。

**フロー名**（例：vantage2sf）および**フローの説明（オプション）** を入力し、**暗号化設定のカスタマイズ（詳細）** のチェックは外したままにします。[**次へ**]をクリックします。


# ステップ2. フローを構成する
このステップでは、フローの送信元と送信先に関する情報を提供します。この例では、ソースとして**Amazon S3**を使用し、デスティネーションとして**Salesforce**を使用する予定です。

・**Sourceの詳細**は、Amazon S3を選択し、CSVファイルを書き込んだバケットを選択します（例：vantagecsv）。
・**Destinationの詳細**は、Salesforceを選択し、**Choose Salesforce connection**のドロップダウンリストでStep1で作成した接続を使用し、Leadは**Choose Salesforce object**を選択します。
・**エラー処理**には、デフォルトの［Stop the current flow run］を使用します。
・**フロートリガー**はRun on demandです。[**Next**］をクリックします。

# ステップ3. データフィールドをマッピングする
このステップでは、ソースからデスティネーションへのデータ転送の方法を決定します。
・**マッピング方法**として、手動でフィールドをマッピングするを使用する
・**宛先レコードの優先順位**として［新しいレコードを挿入する］（デフォルト）を使用します。
・**送信元と送信先のマッピング**には、次のマッピングを使用します。

![画像32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/38a70976-55b6-d28d-d026-daf7a3c5b61c.png)

・[**次へ**」をクリックします。

# ステップ4．フィルターを追加する
転送するレコードを決定するためのフィルタを指定することができます。この例では、フィルターは追加されません。[**次へ**」をクリックします。

# ステップ5. レビューと作成
今入力したすべての情報を確認します。必要であれば修正します。[**フローの作成**］をクリックします。

フローが作成されると、フロー情報とともにフロー作成成功のメッセージが表示されます。


# フローの実行
右上の[**フローの実行**]をクリックします。

フローの実行が完了すると、実行に成功したことを示すメッセージが表示されます。

メッセージの例
![画像33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/6238b542-177a-3cee-4661-2548500f674f.png)


Salesforceのページを参照すると、新しいリードTom Johnsonが追加されています。
![画像34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2742714/e848298f-7f6d-0498-da88-44602d1b18af.png)

# クリーンアップ (オプション)
Salesforceのデータ処理が完了したら、使用したリソースがAWSアカウント（[AppFlow](https://aws.amazon.com/appflow/pricing/)、Amazon [S3](https://aws.amazon.com/s3/pricing/)、[Vantage](https://www.teradata.com/Cloud/AWS/Do-it-Yourself/Pricing)、[VM](https://aws.amazon.com/ec2/pricing/)など）に請求されないように、以下の手順を実行します。


①	AppFlowです。
○フローに作成した「コネクション」を削除する。
○フローを削除する。

②	Amazon S3バケットとファイル
○Vantage データファイルが保存されている Amazon S3 バケットに移動し、ファイルを削除します。
○バケットを保持する必要がない場合は、バケットを削除します。

③	Teradata Vantageインスタンス
○不要になったインスタンスを停止/終了します。

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