# 数组类型
数组是一组数据的集合。数组类型允许在单个数据库字段中存储多个值。数组类型通常用于存储和处理具有相似属性的数据。
#### 语法格式
```
ARRAY [ param ]
```
或
```
'{ param }'
```
其中参数param说明如下：
- param ：数组包含的值，允许出现零个或多个，多个值之间用逗号分隔，没有值可填写为NULL。
- 以'{ param}' 这种格式作为数组常量时，其中的字符串类型的元素不能再以单引号开始和结束，需要使用双引号。两个连续单引号转换为一个单引号。
- 以第一个元素的数据类型作为数组的数据类型，要求数组中所有元素的类型相同，或者能够相互转换。
 
#### 数组类型的定义
一个数组数据类型可以通过在数组元素的数据类型名称后面加上方括号（\[\]）来命名。
例如，创建表books，其中表示书本价格的列price的类型为一维integer类型数组，表示书本标签的列tag的类型为二维text类型数组。
```
CREATE TABLE books (id SERIAL PRIMARY KEY, title VARCHAR(100), price_by_quarter int[], tags TEXT[][]);
```
CREATE TABLE语法可以指定数组的大小，例如：
```
CREATE TABLE test ( a int[3]);
```
当前的数据库实现会忽略语句中数组的大小限制，即其行为与未指定长度的数组相同。同时，也不会强制所声明的维度数。一个特定元素类型的数组全部被当作是相同的类型，而忽略其大小或维度数。
也可以使用关键词ARRAY来定义一维数组。表books中的列price使用ARRAY定义并指定数组大小，如下所示：
```
price_by_quarter int ARRAY[4]
```
使用ARRAY定义，不指定数组尺寸：
```
price_by_quarter int ARRAY
```
#### 数组值输入
输入数组值时要把一个数组值写成一个文字常数，将元素值用花括号包围并用逗号分隔。一个数组常量的一般格式如下：
```
'{ val1 delim val2 delim ... }'
```
其中，delim是类型的定界符，每个val可以是数组元素类型的一个常量或子数组。
一个数组常量的例子如下：
```
'{{1,2,3},{4,5,6},{7,8,9}}'
```
该常量是一个二维的，3乘3数组，它由3个整数子数组构成。
向表books插入数据并查询表books：
```
INSERT INTO books 
  VALUES (1, 'One Hundred Years of Solitude','{25,25,25,25}','{{"fiction"}, {"adventure"}}'),
         (2, 'Robinson Crusoe', '{30,32,32,32}', '{{"adventure"}, {"fiction"}}'),
         (3, 'Gone with the Wind', '{27,27,29,28}', '{{"romance"}, {"fantasy"}}');  
 
SELECT * FROM books;
 id |             title             | price_by_quarter |          tags
----+-------------------------------+------------------+-------------------------
  1 | One Hundred Years of Solitude | {25,25,25,25}    | {{fiction},{adventure}}
  2 | Robinson Crusoe               | {30,32,32,32}    | {{adventure},{fiction}}
  3 | Gone with the Wind            | {27,27,29,28}    | {{romance},{fantasy}}
(3 rows)
```
![](https://support.huaweicloud.com/sqlreference-dws/public_sys-resources/caution_3.0-zh-cn.png)
插入多维数组数据时，多维数组的每一维都必须有相匹配的长度。
使用ARRAY关键字插入数据：
```
INSERT INTO books 
  VALUES (1, 'One Hundred Years of Solitude', ARRAY[25,25,25,25], ARRAY['fiction', 'adventure']),
         (2, 'Robinson Crusoe', ARRAY[30,32,32,32], ARRAY['adventure', 'fiction']),
         (3, 'Gone with the Wind', ARRAY[27,27,29,28], ARRAY['romance', 'fantasy']);
```
#### 访问数组
**访问数组元素**
查询在第二季度价格发生变化的书籍的名称：
```
SELECT title FROM books WHERE price_by_quarter[1] <> price_by_quarter[2];
      title
-----------------
 Robinson Crusoe
(1 row)
```
查询检索所有书籍第三季度的价格：
```
SELECT price_by_quarter[3] FROM books;
 price_by_quarter
------------------
               29
               25
               32
(3 rows)
```
**访问数组切片**
可以访问一个数组的任意矩形切片或者子数组。一个数组切片可以通过在一个或多个数组维度上指定\[下界:上界\]来定义。
查询Gone with the Wind的第二个标签：
```
SELECT tags[2:2] FROM books WHERE title = 'Gone with the Wind';
   tags
-----------
 {fantasy}
(1 row)
```
**使用函数访问数组**
使用array_dims函数获得数组值的当前维度：
```
SELECT array_dims(tags) FROM books WHERE title = 'Robinson Crusoe';
 array_dims
------------
 [1:2]
(1 row)
```
也可以使用array_upper和array_lower来获得数组维度，它们将分别返回一个指定数组的上界和下界：
```
SELECT array_upper(tags, 1) FROM books WHERE title = 'Robinson Crusoe';
 array_upper
-------------
           2
(1 row)
```
array_length函数将返回一个指定数组维度的长度：
```
SELECT array_length(tags, 1) FROM books WHERE title = 'Robinson Crusoe';
 array_length
--------------
            2
(1 row)
```
#### 修改数组
**更新数组**
更新整个数组数据：
```
UPDATE books SET price_by_quarter = '{30,30,30,30}'
     WHERE title = 'Robinson Crusoe';
```
使用ARRAY表达式语法更新整个数组数据：
```
UPDATE books SET price_by_quarter = ARRAY[30,30,30,30]
     WHERE title = 'Robinson Crusoe';
```
更新数组中的一个元素：
```
UPDATE books SET price_by_quarter[4] = 35
     WHERE title = 'Robinson Crusoe';
```
更新数组中的一个切片元素：
```
UPDATE books SET price_by_quarter[1:2] = '{27,27}'
     WHERE title = 'Robinson Crusoe';
```
一个已存储的数组值可以被通过对其还不存在的元素赋值来扩大大小。任何位于已存在的元素和新元素之间的位置都将被空值填充。例如，如果数组myarray目前有4个元素，使用UPDATE对myarray\[6\]赋值后它将有6个元素，其中myarray\[5\]为空值。目前，采用这种方式扩大数组只允许使用在一维数组上。
**构建新数组**
新的数组值也可以通过串接操作符"\|\|"构建。串接操作符允许把一个单独的元素加入到一个一维数组的开头或末尾。也可接受两个N维数组，或者一个N维数组和一个N+1维数组。
```
SELECT ARRAY[1,2] || ARRAY[3,4];
 ?column?
-----------
 {1,2,3,4}
(1 row)
SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]];
      ?column?
---------------------
 {{5,6},{1,2},{3,4}}
(1 row)
```
使用函数array_prepend、array_append或array_cat构建数组。
```
SELECT array_prepend(1, ARRAY[2,3]);
 array_prepend
---------------
 {1,2,3}
(1 row)
SELECT array_append(ARRAY[1,2], 3);
 array_append
--------------
 {1,2,3}
(1 row)
SELECT array_cat(ARRAY[1,2], ARRAY[3,4]);
 array_cat
-----------
 {1,2,3,4}
(1 row)
SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]);
      array_cat
---------------------
 {{1,2},{3,4},{5,6}}
(1 row)
SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]);
      array_cat
---------------------
 {{5,6},{1,2},{3,4}}
(1 row)
```
