
# 复杂数据类型
Spark SQL支持复杂数据类型，如[表1]所示。
 表1复杂数据类型 
| **数据类型** | **描述**                                                                                      | **使用格式**                                                                                                                                                                                                                                                                                           |
|:---|:---|:---|
| ARRAY    | 一组有序字段，使用指定的值构造ARRAY数组。可以为任意类型，要求所有字段的数据类型必须相同。                                             | array(\<value\>,\<value\>\[, ...\]) 具体使用示例详见：[ARRAY示例]。                         |
| MAP      | 一组无序的键/值对，使用给定的Key和Value对生成MAP。键的类型必须是原生数据类型，值的类型可以是原生数据类型或复杂数据类型。同一个MAP键的类型必须相同，值的类型也必须相同。 | map(K \<key1\>, V \<value1\>, K \<key2\>, V \<value2\>\[, ...\]) 具体使用示例详见：[MAP示例]。 |
| STRUCT   | 一组命名的字段，字段的数据类型可以不同。                                                                        | struct(\<value1\>,\<value2\>\[, ...\]) 具体使用示例详见：[STRUCT示例]。                     |
   
#### 使用限制
- 创建含有复杂数据类型字段的表时，该表存储格式不支持CSV（txt）。
- 如果表中含有复杂数据类型字段时，该表不支持CSV（txt）格式的文件数据导入。
- MAP数据类型建表必须指定schema，且不支持date、short、timestamp数据类型。
- 对于JSON格式OBS表，MAP的键类型只支持STRING类型。
- 由于MAP类型的键不能为NULL，MAP键不支持对插入数据进行可能出现NULL值类型之间的隐式转换，如：STRING类型转换为其他原生类型、FLOAT类型转换为TIMESTAMP类型、其他原生类型转换为DECIMAL类型等。
- STRUCT数据类型不支持double，boolean数据类型。
 
 #### ARRAY示例
创建表"array_test"，将"id"参数定义为"ARRAY\<INT\>"数据类型，"name"参数定义为"STRING"数据类型。建表成功后插入测试数据到"array_test"中。操作如下：
1. 创建表。 **CREATE TABLE array_test(name STRING, id ARRAY \< INT \>) USING PARQUET;**
   
2. 插入测试数据。 **INSERT INTO array_test VALUES ('test',array(1,2,3,4));**
   **INSERT INTO array_test VALUES ('test2',array(4,5,6,7));**
   **INSERT INTO array_test VALUES ('test3',array(7,8,9,0));**
   
3. 查询结果。 查"array_test"表中的所有数据：
   **SELECT \* FROM** **array_test**;
   ```
   test3[7,8,9,0]
   test2[4,5,6,7]
   test[1,2,3,4]
   ```
   查"array_test"表中id数组第0个元素的数据。
   **SELECT id\[0\] FROM** **array_test**;
   ```
   7
   4
   1
   ```
   
 
 #### MAP示例
创建表"map_test"，将"score"参数定义为"map\<STRING,INT\>"数据类型（键为STRING类型，值为INT类型）。建表成功后插入测试数据至"map_test"中。操作如下：
1. 创建表。 **CREATE TABLE map_test(id STRING, score map\<STRING,INT\>) USING PARQUET;**
   
2. 插入测试数据。 **INSERT INTO map_test VALUES ('test4',map('math',70,'chemistry',84));**
   **INSERT INTO map_test VALUES ('test5',map('math',85,'chemistry',97));**
   **INSERT INTO map_test VALUES ('test6',map('math',88,'chemistry',80));**
   
3. 查询结果。 查询"map_test"表里的所有数据。
   **SELECT \* FROM map_test;**
   ```
   test6{"chemistry":80,"math":88}
   test5{"chemistry":97,"math":85}
   test4{"chemistry":84,"math":70}
   ```
   查询"map_test"表中的数学成绩。
   **SELECT id, score\['math'\] FROM map_test;**
   ```
   test688
   test585
   test470
   ```
   
 
 #### STRUCT示例
创建表"struct_test"，将info定义为"STRUCT\<name:STRING, age:INT\>"数据类型（由name和age构成的字段，其中name为STRING类型，age为INT类型）。建表成功后插入测试数据至"struct_test"表中。操作如下：
1. 创建表。 **CREATE TABLE struct_test(id INT, info STRUCT\<name:STRING,age:INT\>) USING PARQUET;**
   
2. 插入测试数据。 **INSERT INTO struct_test VALUES (8, struct('user1',23));**
   **INSERT INTO struct_test VALUES (9, struct('user2',25));**
   **INSERT INTO struct_test VALUES (10, struct('user3',26));**
   
3. 查询结果。 查询"struct_test"表中的所有数据。
   **SELECT \* FROM struct_test;**
   ```
   8{"name":"user1","age":23}
   10{"name":"user2","age":26}
   9{"name":"user3","age":25}
   ```
   查询"struct_test"表中的**name** 和**age**数据。
   **SELECT id,info.name,info.age FROM struct_test;**
   ```
   8       user1   23
   10      user2   26
   9user325
   ```
   
 
