

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

# Amazon Athena 中的資料類型
<a name="data-types"></a>

當您執行 `CREATE TABLE` 時，您需指定資料欄名稱和每個資料欄可包含的資料類型。您建立的資料表會存放在 AWS Glue Data Catalog中。

為了促進與其他查詢引擎的互通性，Athena 會對 DDL 陳述式 (例如 `CREATE TABLE`) 使用 [Apache Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types) 資料類型名稱。對於 `SELECT`、`CTAS` 和 `INSERT INTO` 等 DML 查詢，Athena 會使用 [Trino](https://trino.io/docs/current/language/types.html) 資料類型名稱。下列資料表會顯示 Athena 支援的資料類型。當 DDL 和 DML 類型在名稱、可用性或語法等方面有所不同時，它們會顯示在不同的資料欄中。


****  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/athena/latest/ug/data-types.html)

**Topics**
+ [

# 資料類型範例
](data-types-examples.md)
+ [

# 資料類型的考量事項
](data-types-considerations.md)
+ [

# 使用時間戳記資料
](data-types-timestamps.md)

# 資料類型範例
<a name="data-types-examples"></a>

下列資料表會顯示 DML 資料類型的範例常值。


****  

| 資料類型 | 範例 | 
| --- | --- | 
| BOOLEAN |  `true` `false `  | 
| TINYINT |  `TINYINT '123'`  | 
| SMALLINT |  `SMALLINT '123'`  | 
| INT、INTEGER |  `123456790`  | 
| BIGINT |  `BIGINT '1234567890'` `2147483648`  | 
| REAL |  `'123456.78'`  | 
| DOUBLE |  `1.234`  | 
| DECIMAL(precision, scale) |  `DECIMAL '123.456'`  | 
| CHAR, CHAR(length) |  `CHAR 'hello world'`, `CHAR 'hello ''world''!'`  | 
| VARCHAR, VARCHAR(length) |  `VARCHAR 'hello world'`, `VARCHAR 'hello ''world''!'`  | 
| VARBINARY |  `X'00 01 02'`  | 
| TIME, TIME(precision) |  `TIME '10:11:12'`, `TIME '10:11:12.345'`  | 
| TIME WITH TIME ZONE |  `TIME '10:11:12.345 -06:00'`  | 
| DATE |  `DATE '2024-03-25'`  | 
|  TIMESTAMP, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP(*precision*), TIMESTAMP(*precision*) WITHOUT TIME ZONE   |  `TIMESTAMP '2024-03-25 11:12:13'`, `TIMESTAMP '2024-03-25 11:12:13.456'`  | 
| TIMESTAMP WITH TIME ZONE, TIMESTAMP(precision) WITH TIME ZONE |  `TIMESTAMP '2024-03-25 11:12:13.456 Europe/Berlin'`  | 
| INTERVAL YEAR TO MONTH |  `INTERVAL '3' MONTH`  | 
| INTERVAL DAY TO SECOND |  `INTERVAL '2' DAY`  | 
| ARRAY[element\$1type] |  `ARRAY['one', 'two', 'three']`  | 
| MAP(key\$1type, value\$1type) |  `MAP(ARRAY['one', 'two', 'three'], ARRAY[1, 2, 3])` 請注意，映射是從索引鍵陣列和值陣列建立的。下列範例會建立將字串映射為整數的資料表。 <pre>CREATE TABLE map_table(col1 map<string, integer>) LOCATION '...';<br />INSERT INTO map_table values(MAP(ARRAY['foo', 'bar'], ARRAY[1, 2]));</pre>  | 
| ROW(field\$1name\$11 field\$1type\$11, field\$1name\$12 field\$1type\$12, …) |  `ROW('one', 'two', 'three')` 請注意，以這種方式建立的資料列沒有資料欄名稱。若要新增資料欄名稱，可以使用 `CAST`，如下列範例所示： <pre>CAST(ROW(1, 2, 3) AS ROW(one INT, two INT, three INT))</pre>  | 
| JSON |  `JSON '{"one":1, "two": 2, "three": 3}'`  | 
| UUID |  `UUID '12345678-90ab-cdef-1234-567890abcdef'`  | 
| IPADDRESS |  `IPADDRESS '10.0.0.1'` `IPADDRESS '2001:db8::1'`  | 

# 資料類型的考量事項
<a name="data-types-considerations"></a>

## 大小限制
<a name="data-types-considerations-size"></a>

對於未指定大小限制的資料類型，請記住，單一資料列中所有資料的實際限制為 32MB。如需詳細資訊，請參閱 [在 Amazon Athena 中進行 SQL 查詢的考量事項與限制](other-notable-limitations.md) 中的 [Row or column size limitation](other-notable-limitations.md#sql-limitations-rowsize)。

## CHAR 和 VARCHAR
<a name="data-types-considerations-char"></a>

`CHAR(n)` 值的計數一律為 `n` 個字元。例如，如果您將 'abc' 轉換為 `CHAR(7)`，則會新增 4 個尾隨空格。

`CHAR` 值的比較包括前導和尾隨空格。

如果為 `CHAR` 或 `VARCHAR` 指定，讀取字串時，會以指定的長度進行截斷。如果基礎資料字串較長，則基礎資料字串會維持不變。

若要逸出 `CHAR` 或 `VARCHAR` 中的單引號，請使用額外的單引號。

若要將非字串資料類型轉換為 DML 查詢中的字串，請轉換為 `VARCHAR` 資料類型。

若要使用 `substr` 函式從 `CHAR` 資料類型傳回指定長度的子字串，您必須先將 `CHAR` 值轉換為 `VARCHAR`。在下列範例中，`col1` 使用 `CHAR` 資料類型。

```
substr(CAST(col1 AS VARCHAR), 1, 4)
```

## DECIMAL
<a name="data-types-considerations-decimal"></a>

若要在 `SELECT` 查詢中指定小數值為常值，例如以特定小數值選取資料列，可指定 `DECIMAL` 類型，並在查詢中以單引號列出小數值為常值，如下列範例所示。

```
SELECT * FROM my_table
WHERE decimal_value = DECIMAL '0.12'
```

```
SELECT DECIMAL '44.6' + DECIMAL '77.2'
```

# 使用時間戳記資料
<a name="data-types-timestamps"></a>

本節說明在 Athena 中使用時間戳記資料的一些考量。

**注意**  
先前的引擎版本與 Athena 引擎版本 3 之間的時間戳記處理方式發生變更。如需有關 Athena 引擎版本 3 中可能發生的時間戳記相關錯誤及建議的解決方案的資訊，請參閱 [Athena 引擎版本 3](engine-versions-reference-0003.md) 參考中的 [時間戳記變更](engine-versions-reference-0003.md#engine-versions-reference-0003-timestamp-changes)。

## 將時間戳記資料寫入 Amazon S3 物件的格式
<a name="data-types-timestamps-writing-to-s3-objects"></a>

將時間戳記資料寫入 Amazon S3 物件的格式，取決於您使用的資料欄資料類型和 [SerDe 程式庫](https://docs.aws.amazon.com/athena/latest/ug/supported-serdes.html)。
+ 如果您有類型為 `DATE` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是 ISO 格式的字串 `YYYY-MM-DD`，或是內建的日期類型 (例如 Parquet 或 ORC 的日期類型)。
+ 如果您有類型為 `TIME` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是 ISO 格式的字串 `HH:MM:SS`，或是內建的時間類型 (例如 Parquet 或 ORC 的時間類型)。
+ 如果您有類型為 `TIMESTAMP` 的資料表資料欄，Athena 會預期資料的對應資料欄或屬性是格式的字串 `YYYY-MM-DD HH:MM:SS.SSS` (注意日期和時間之間的空格)，或是內建的時間類型 (例如 Parquet、ORC 或 Ion 的時間類型)。請注意，Athena 不保證對無效時間戳記的行為 （例如 `0000-00-00 08:00:00.000`)。
**注意**  
OpenCSVSerDe 時間戳記是例外狀況，且必須編碼為毫秒解析度的 UNIX epochs。

## 確保時間分割資料符合記錄中的時間戳記欄位
<a name="data-types-timestamps-time-partitioned-data-and-timestamp-fields"></a>

資料的產生者必須確定分割區值與分割區內的資料一致。例如，如果您的資料具有 `timestamp` 屬性，而您使用 Firehose 將資料載入 Amazon S3，則必須使用[動態分割](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html)，因為 Firehose 的預設分割以掛鐘為基礎的。

## 使用字串做為分割區索引鍵的資料類型
<a name="data-types-timestamps-partition-key-types"></a>

出於效能考量，最好將 `STRING` 用作分割區索引鍵的資料類型。雖然 Athena 將格式 `YYYY-MM-DD` 的分割區值識別為您使用 `DATE` 類型時的日期，而這可能造成效能不彰。因此，我們建議您改用 `STRING` 資料類型做為分割區索引鍵。

## 如何寫入同樣按時間分割的時間戳記欄位的查詢
<a name="data-types-timestamps-how-to-write-queries-for-timestamp-fields-that-are-also-time-partitioned"></a>

如何寫入同樣按時間分割的時間戳記欄位的查詢，取決於您要查詢的資料表的類型。

### Hive 資料表
<a name="data-types-timestamps-hive-tables"></a>

使用 Athena 中最常用的 Hive 資料表，查詢引擎對資料欄和分割區索引鍵之間的關係一無所知。因此，您必須始終在資料欄和分割區索引鍵的查詢中新增述詞。

例如，假設您有 `event_time` 資料欄和 `event_date` 分割區索引鍵，而且想要查詢 23:00 到 03:00 之間的事件。在此案例中，您必須在查詢資料欄和分割區索引鍵中包含述詞，如下列範例所示。

```
WHERE event_time BETWEEN start_time AND end_time 
  AND event_date BETWEEN start_time_date AND end_time_date
```

### Iceberg 資料表
<a name="data-types-timestamps-iceberg-tables"></a>

使用 Iceberg 資料表，您可以使用運算的分割區值，從而簡化查詢。例如，假設您的 Iceberg 資料表是使用如下 `PARTITIONED BY` 子句建立的：

```
PARTITIONED BY (event_date month(event_time))
```

在此案例下，查詢引擎會根據 `event_time` 述詞的值自動剔除分割區。因此，您的查詢只需要指定 `event_time` 的述詞，如下列範例所示。

```
WHERE event_time BETWEEN start_time AND end_time
```

如需詳細資訊，請參閱[建立 Iceberg 資料表](querying-iceberg-creating-tables.md)。

對時間戳記資料欄使用 Iceberg 的隱藏分割時，Iceberg 可能會在衍生自時間戳記資料欄的建構資料表資料欄上建立分割區，並將其轉換為日期，以實現更有效的分割。例如，它可能會從時間戳記資料欄 `event_time` 建立 `event_date`，並在 `event_date` 上自動進行分割。在這種情況下，分割區**類型**是**日期**。

為了在使用分割區時獲得最佳查詢效能，請篩選全天範圍以啟用述詞下推。例如，下列查詢不會下推，因為範圍無法轉換為單一日期分割區，即使其恰到落在一天內：

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-18 12:00:00'
```

相反地，請使用全天範圍來允許述詞下推，並提升查詢效能，如下列範例所示。

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-19 00:00:00'
```

您也可以使用 `BETWEEN start_time AND end_time` 語法或使用多日範圍，只要時間戳記部分為 `00:00:00` 即可。

如需詳細資訊，請參閱 [Trino 部落格文章](https://trino.io/blog/2023/04/11/date-predicates.html)。