

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 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` 不支援聯合查詢。嘗試執行這項操作可能會產生錯誤訊息：外部目錄目前不支援此操作。如需聯合查詢的詳細資訊，請參閱[使用 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` 的查詢會將來源資料表中的最後一個資料欄的值，認定為目標資料表中的分割區資料欄的值。嘗試從未分割的資料表建立分割的資料表時，請注意以上提醒。

#### Resources
<a name="insert-into-partition-resources"></a>

如需有關搭配分割使用 `INSERT INTO` 的詳細資料，請參閱以下資源。
+ 如需將分割的資料插入分割的資料表，請參閱[使用 CTAS 和 INSERT INTO 來解決 100 個分割區限制](ctas-insert-into.md)。
+ 如需將未分割的資料插入分割的資料表，請參閱[使用 CTAS 和 INSERT INTO 以進行 ETL 和資料分析](ctas-insert-into-etl.md)。

### 寫入 Amazon S3 的檔案
<a name="insert-into-files-written-to-s3"></a>

`INSERT` 命令執行之後，Athena 會將檔案寫入 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 不會重寫或修改現有檔案。相反地，它會將這些資料列寫入一或多個新檔案中。由於資料表[擁有許多小型檔案，進而導致查詢效能降低](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`。相反地，請將資料列累積到較大的檔案中，然後直接上傳至 Amazon S3，其中 Athena 可以在其中查詢這些資料。

### 尋找孤立檔案
<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>

指定在一個資料表上執行的查詢：`source_table`，這會決定要插入第二個資料表的資料列：`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;
```

僅選取 `vancouver_pageviews` 資料表中的列，其中 `date` 資料欄有介於 `2019-07-01` 到 `2019-07-31` 間的值，然後將其插入 `canada_july_pageviews`：

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

請僅從 `country` 資料欄中 `usa` 的值選取 `cities_world` 資料表中 `city` 與 `state` 欄內的值，並將其插入 `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>

透過指定資料欄和值，將資料列插入現有的資料表。指定的資料欄和相關聯的資料類型必須精確地符合目標資料表中的資料欄和資料類型。

**重要**  
我們不建議使用 `VALUES` 插入資料行，因為 Athena 會為每個 `INSERT` 操作產生檔案。這可能會導致建立許多小型檔案，並降低資料表的查詢效能。若要識別 `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`。`id` 資料欄的類型是 `INT`，而其他所有欄的類型都是 `VARCHAR`。

將單一列插入 `cities` 資料表，並指定所有資料欄值：

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

在 `cities` 資料表中插入兩列：

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