

# INSERT INTO
<a name="insert-into"></a>

ソーステーブルで実行される `SELECT` クエリステートメント、またはステートメントの一部として提供される `VALUES` のセットに基づいて、送信先テーブルに新しい行を挿入します。ソーステーブルが CSV や JSON などの形式の基盤データに基づくもので、宛先テーブルが Parquet や ORC など別の形式に基づいている場合は、`INSERT INTO` クエリを使用して、選択したデータを宛先テーブルの形式に変換できます。

## 考慮事項と制限事項
<a name="insert-into-limitations"></a>

Athena で `INSERT` クエリを使用するときは、以下の点を考慮してください。
+ Amazon S3 で暗号化された基盤データがあるテーブルに対して `INSERT` クエリを実行する場合、`INSERT` クエリが書き込む出力ファイルはデフォルトで暗号化されません。暗号化されたデータを含むテーブルに挿入する場合は、`INSERT` クエリの結果を暗号化することをお勧めします。

  コンソールを使用したクエリ結果の暗号化の詳細については、「[Amazon S3 に保存された Athena クエリ結果を暗号化する](encrypting-query-results-stored-in-s3.md)」を参照してください。AWS CLI または Athena API を使用した暗号化を有効にするには、[StartQueryExecution](https://docs.aws.amazon.com/athena/latest/APIReference/API_StartQueryExecution.html) アクションの `EncryptionConfiguration` プロパティを使用して、要件に沿った Amazon S3 暗号化オプションを指定します。
+ `INSERT INTO` ステートメントの場合、予想されるバケット所有者の設定は、Amazon S3 内の送信先テーブルのロケーションには適用されません。予期されるバケット所有者の設定は、Athena クエリの結果の出力先として指定した Amazon S3 内の場所にのみ適用されます。詳細については、「[Athena コンソールを使用してクエリ結果の場所を指定する](query-results-specify-location-console.md)」を参照してください。
+ ACID 準拠の `INSERT INTO` ステートメントについては、[Iceberg テーブルデータを更新する](querying-iceberg-updating-iceberg-table-data.md) の `INSERT INTO` セクションを参照してください。

### サポートされる形式と SerDes
<a name="insert-into-supported-formats"></a>

次の形式と SerDes を使用して、データから作成されたテーブルに対して `INSERT` クエリを実行できます。


| データ形式 | SerDe | 
| --- | --- | 
|  Avro  |  org.apache.hadoop.hive.serde2.avro.AvroSerDe  | 
| Ion | com.amazon.ionhiveserde.IonHiveSerDe | 
|  JSON  |  org.apache.hive.hcatalog.data.JsonSerDe  | 
|  ORC  |  org.apache.hadoop.hive.ql.io.orc.OrcSerde  | 
|  Parquet  |  org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe  | 
|  テキストファイル  |  org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe  TSV、およびカスタム区切りファイルがサポートされています。   | 
| CSV | org.apache.hadoop.hive.serde2.OpenCSVSerde 書き込みは文字列型でのみサポートされます。Athena から、Glue スキーマに文字列以外の型を含むテーブルに書き込むことはできません。詳細については、「[CSV SerDe](csv-serde.md#csv-serde-opencsvserde-considerations-non-string)」を参照してください。  | 

### バケット化されたテーブルはサポートされていません
<a name="insert-into-bucketed-tables-not-supported"></a>

`INSERT INTO` はバケット化されたテーブルではサポートされていません。詳細については、「[パーティショニングとバケット化を使用する](ctas-partitioning-and-bucketing.md)」を参照してください。

### フェデレーティッドクエリはサポートされていません
<a name="insert-into-federated-queries-not-supported"></a>

横串検索では、`INSERT INTO` はサポートされていません。これを試みた場合、「This operation is currently not supported for external catalogs (この操作は現在、外部カタログではサポートされていません)」というエラーメッセージが表示されることがあります。横串検索の詳細については、「[Amazon Athena フェデレーティッドクエリを使用する](federated-queries.md)」を参照してください。

### パーティション
<a name="insert-into-limitations-partitioning"></a>

`INSERT INTO` または `CREATE TABLE AS SELECT` クエリでパーティションを使用するときは、このセクションのポイントを考慮してください。

#### 制限
<a name="insert-into-partition-limits"></a>

この `INSERT INTO` ステートメントは、送信先テーブルへの最大 100  個のパーティションの書き込みをサポートします。100 個を超えるパーティションを持つテーブルから `SELECT` 句を使用して行を追加する場合、`SELECT` クエリは、100 個以下のパーティションに制限されない限り失敗します。

この制限を回避する方法については、「[CTAS および INSERT INTO を使用して 100 パーティションの制限を回避する](ctas-insert-into.md)」を参照してください。

#### 列の順序
<a name="insert-into-partition-detection"></a>

`INSERT INTO` または `CREATE TABLE AS SELECT` ステートメントは、`SELECT` ステートメントで射影された列のリストの最後の列がパーティションされた列であることを期待します。

ソーステーブルがパーティションされていない場合、または宛先テーブルとは異なる列でパーティションされている場合、`INSERT INTO destination_table SELECT * FROM source_table` のようなクエリは、ソーステーブルの最後の列の値が宛先テーブルのパーティション列の値であると見なします。パーティションされていないテーブルからパーティションテーブルを作成するときは、この点に留意してください。

#### リソース
<a name="insert-into-partition-resources"></a>

パーティションでの `INSERT INTO` の使用に関する詳細については、以下のリソースを参照してください。
+ パーティションされたデータをパーティションテーブルに挿入する方法については、「[CTAS および INSERT INTO を使用して 100 パーティションの制限を回避する](ctas-insert-into.md)」を参照してください。
+ パーティションされていないデータをパーティションテーブルに挿入する方法については、「[ETL およびデータ分析での CTAS および INSERT INTO を使用する](ctas-insert-into-etl.md)」を参照してください。

### Amazon S3 に書き込まれるファイル
<a name="insert-into-files-written-to-s3"></a>

Athena は、`INSERT` コマンドの結果として、Amazon S3 のソースデータの場所にファイルを書き込みます。`INSERT` オペレーションごとに、既存のファイルを追加するのではなく、新しいファイルが作成されます。ファイルの場所は、テーブルの構造と `SELECT` クエリ (存在する場合) に応じて異なります。Athena は、`INSERT` クエリごとにデータマニフェストファイルを生成します。マニフェストは、クエリが書き込んだファイルを追跡します。これは、Amazon S3 にある Athena のクエリ結果の場所に保存されます。詳細については、「[クエリ出力ファイルを識別する](querying-finding-output-files.md#querying-identifying-output-files)」を参照してください。

### トランザクション集約型更新の回避
<a name="insert-into-transactional-caveat"></a>

`INSERT INTO` を使用して Amazon S3 内のテーブルに行を追加しても、Athena は既存のファイルの書き換えや変更を行いません。その代わりに、Athena は 1 つ、または複数の新しいファイルとして行を書き込みます。[小さなファイルが多数存在するテーブルはクエリパフォーマンスの低下につながり](performance-tuning-data-optimization-techniques.md#performance-tuning-avoid-having-too-many-files)、`PutObject` や `GetObject` などの書き込みおよび読み取り操作は Amazon S3 のコスト増加につながるため、`INSERT INTO` を使用するときは以下のオプションを検討してください。
+ 行の大規模なバッチに対する `INSERT INTO` 操作の実行頻度を減らす。
+ データインジェスト量が多い場合は、[Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) といったサービスの使用を検討する。
+ もとより `INSERT INTO` を使用しないようにする。その代わりに、より大きなファイルに行を蓄積し、Athena が行をクエリできる Amazon S3 に直接アップロードします。

### 孤立したファイルの検索
<a name="insert-into-files-partial-data"></a>

`CTAS` または `INSERT INTO` ステートメントが失敗すると、孤立したデータがデータの場所に残され、後続のクエリで読み取られる場合があります。検査または削除する孤立したファイルを見つけるには、Athena に用意されているデータマニフェストファイルを使用して、書き込まれるファイルのリストを追跡できます。詳細については、「[クエリ出力ファイルを識別する](querying-finding-output-files.md#querying-identifying-output-files)」および「[DataManifestLocation](https://docs.aws.amazon.com/athena/latest/APIReference/API_QueryExecutionStatistics.html#athena-Type-QueryExecutionStatistics-DataManifestLocation)」を参照してください。

## INSERT INTO...SELECT
<a name="insert-into-select"></a>

1 つのテーブル、`source_table` に対して実行するクエリを指定します。これにより、2 番目のテーブル、`destination_table` に挿入する行が決定されます。`SELECT` クエリが `source_table` での列を指定する場合、その列は `destination_table` の列と正確に一致する必要があります。

`SELECT` クエリの詳細については、「[SELECT](select.md)」を参照してください。

### 概要
<a name="insert-into-select-synopsis"></a>

```
INSERT INTO destination_table 
SELECT select_query 
FROM source_table_or_view
```

### 例
<a name="insert-into-select-examples"></a>

`vancouver_pageviews` テーブル内のすべての行を選択し、`canada_pageviews` テーブルに挿入します。

```
INSERT INTO canada_pageviews 
SELECT * 
FROM vancouver_pageviews;
```

`date` 列の値が `2019-07-01`～`2019-07-31` の `vancouver_pageviews` テーブル内の行のみを選択し、`canada_july_pageviews` に挿入します。

```
INSERT INTO canada_july_pageviews
SELECT *
FROM vancouver_pageviews
WHERE date
    BETWEEN date '2019-07-01'
        AND '2019-07-31';
```

`cities_world` テーブルの `city` と `state` 列で、`country` 列の値が `usa` の行だけを選択して、`cities_usa` テーブルの `city` と `state` 列に挿入します。

```
INSERT INTO cities_usa (city,state)
SELECT city,state
FROM cities_world
    WHERE country='usa'
```

## INSERT INTO...VALUES
<a name="insert-into-values"></a>

列と値を指定して、既存のテーブルに行を挿入します。指定された列と関連するデータ型は、宛先テーブルの列およびデータ型と正確に一致する必要があります。

**重要**  
Athena は `INSERT` オペレーションごとにファイルを生成するため、`VALUES` を使用した行の挿入は推奨されません。これにより、多数の小さなファイルが作成され、テーブルのクエリパフォーマンスが低下する可能性があります。`INSERT` クエリが作成するファイルを識別するには、データマニフェストファイルを調べます。詳細については、「[クエリ結果と最近のクエリを操作する](querying.md)」を参照してください。

### 概要
<a name="insert-into-values-synopsis"></a>

```
INSERT INTO destination_table [(col1,col2,...)] 
VALUES (col1value,col2value,...)[,
       (col1value,col2value,...)][,
       ...]
```

### 例
<a name="insert-into-values-examples"></a>

次の例では、都市テーブルには、`id`、`city`、`state`、`state_motto` の 3 つの列があります。`id` 列は `INT` 型で、他のすべての列は `VARCHAR` 型です。

`cities` テーブルに 1 つの行を挿入し、すべての列の値を指定します。

```
INSERT INTO cities 
VALUES (1,'Lansing','MI','Si quaeris peninsulam amoenam circumspice')
```

`cities` テーブルに 2 行を挿入します。

```
INSERT INTO cities 
VALUES (1,'Lansing','MI','Si quaeris peninsulam amoenam circumspice'),
       (3,'Boise','ID','Esto perpetua')
```