# 8.15.阵列
PostgreSQL允许将表的列定义为可变长度的多维数组。可以创建任何内置或用户定义的基类型、枚举类型、复合类型、范围类型或域的数组。
# 8.15.1.数组类型的声明
为了说明数组类型的使用,我们创建了以下表格:
CREATE TABLE sal_emp (
name text,
pay_by_quarter integer[],
schedule text[][]
);
如图所示,数组数据类型通过附加方括号来命名([]
)指向数组元素的数据类型名称。上面的命令将创建一个名为萨卢恩普
有一列文本
(名称
),类型的一维数组整数
(按季度支付
),按季度表示员工的工资,以及文本
(日程
),表示员工的每周日程安排。
的语法创建表格
允许指定阵列的确切大小,例如:
CREATE TABLE tictactoe (
squares integer[3][3]
);
但是,当前的实现忽略了任何提供的数组大小限制,即,行为与未指定长度的数组相同。
当前实现也不强制执行已声明的维度数。特定元素类型的数组都被视为同一类型,而不管大小或维数如何。因此,在创建表格
仅仅是文件;它不会影响运行时行为。
另一种语法,通过使用关键字符合SQL标准大堆
,可用于一维数组。按季度支付
可以定义为:
pay_by_quarter integer ARRAY[4],
或者,如果不指定数组大小:
pay_by_quarter integer ARRAY,
然而,与之前一样,PostgreSQL在任何情况下都不会强制执行大小限制。
# 8.15.2.数组值输入
要将数组值作为文字常量写入,请将元素值括在大括号内,并用逗号分隔。(如果你知道C,这和初始化结构的C语法没有什么不同。)可以在任何元素值周围加双引号,如果元素值包含逗号或大括号,则必须加双引号。(更多细节见下文。)因此,数组常量的一般格式如下:
'{ val1 delim val2 delim ... }'
哪里*德利姆
是类型的分隔符,记录在pg_型
进入在PostgreSQL发行版中提供的标准数据类型中,所有数据类型都使用逗号(,
),类型除外盒
它使用分号(;
).每人瓦尔
*是数组元素类型的常量或子数组。数组常数的一个例子是:
'{{1,2,3},{4,5,6},{7,8,9}}'
这个常数是一个由三个子整数组成的二维3乘3数组。
要将数组常量的元素设置为NULL,请写入无效的
对于元素值。(任何大写或小写的无效的
可以。)如果你想要一个实际的字符串值“NULL”,你必须在它周围加上双引号。
(这些类型的数组常量实际上只是中讨论的泛型类型常量的一个特例。)第4.1.2.7节。常量最初被视为字符串,并传递给数组输入转换例程。可能需要明确的类型规范。)
现在我们可以展示一些插入
声明:
INSERT INTO sal_emp
VALUES ('Bill',
'{10000, 10000, 10000, 10000}',
'{{"meeting", "lunch"}, {"training", "presentation"}}');
INSERT INTO sal_emp
VALUES ('Carol',
'{20000, 25000, 25000, 25000}',
'{{"breakfast", "consulting"}, {"meeting", "lunch"}}');
前两次插入的结果如下所示:
SELECT * FROM sal_emp;
name | pay_by_quarter | schedule
### 8.15.3. Accessing Arrays
[]()
Now, we can run some queries on the table. First, we show how to access a single element of an array. This query retrieves the names of the employees whose pay changed in the second quarter:
从sal_emp中选择名称,按季度支付[1]<>按季度支付[2];
名称
# 8.15.4.修改数组
可以完全替换数组值:
UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
WHERE name = 'Carol';
或者使用大堆
表达式语法:
UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000]
WHERE name = 'Carol';
数组也可以在单个元素上更新:
UPDATE sal_emp SET pay_by_quarter[4] = 15000
WHERE name = 'Bill';
或在切片中更新:
UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
WHERE name = 'Carol';
省略的切片语法*下限
和/或上限
*也可以使用,但只能在更新非空或零维的数组值时使用(否则,不存在可替换的现有下标限制)。
存储的数组值可以通过分配给尚未存在的元素来放大。以前存在的元素和新分配的元素之间的任何位置都将用空值填充。例如,if数组myarray
当前有4个元素,更新后将有6个元素分配给myarray[6]
; myarray[5]
将包含null。目前,这种方式的放大只允许用于一维数组,而不允许用于多维数组。
下标赋值允许创建不使用基于一的下标的数组。例如,一个人可以分配给myarray[-2:7]
创建下标值为-2到7的数组。
还可以使用串联运算符构造新的数组值,||
:
SELECT ARRAY[1,2] || ARRAY[3,4];
?column?
### 8.15.5. Searching in Arrays
[]()
To search for a value in an array, each value must be checked. This can be done manually, if you know the size of the array. For example:
从sal_emp中选择*按季度支付[1]=10000或按季度支付[2]=10000或按季度支付[3]=10000或按季度支付[4] = 10000;
However, this quickly becomes tedious for large arrays, and is not helpful if the size of the array is unknown. An alternative method is described in [Section 9.24](functions-comparisons.html). The above query could be replaced by:
从sal_emp中选择*,其中10000=任意(按季度支付);
In addition, you can find rows where the array has all values equal to 10000 with:
从sal_emp中选择*其中10000=全部(按季度支付);
Alternatively, the `generate_subscripts` function can be used. For example:
选择*从(选择按季度支付,生成下标(按季度支付,1)作为sal_emp的s)作为foo,其中按季度支付[s] = 10000;
This function is described in [Table 9.64](functions-srf.html#FUNCTIONS-SRF-SUBSCRIPTS).
You can also search an array using the `&&` operator, which checks whether the left operand overlaps with the right operand. For instance:
从sal_emp中选择*按季度和阵列付款[10000];
This and other array operators are further described in [Section 9.19](functions-array.html). It can be accelerated by an appropriate index, as described in [Section 11.2](indexes-types.html).
You can also search for specific values in an array using the `array_position` and `array_positions` functions. The former returns the subscript of the first occurrence of a value in an array; the latter returns an array with the subscripts of all occurrences of the value in the array. For example:
选择阵列位置(阵列)[“sun”、“mon”、“tue”、“wed”、“thu”、“fri”、“sat”']“mon”);阵列位置
# 提示
数组不是集合;搜索特定的数组元素可能是数据库设计错误的标志。考虑为每个项目使用一个单独的表,这将是一个数组元素。这将更容易搜索,并且对于大量元素可能会更好地扩展。
# 8.15.6.数组输入和输出语法
数组值的外部文本表示形式包括根据数组元素类型的I/O转换规则解释的项,以及指示数组结构的装饰。装饰物由花括号组成({
和}
)数组值周围加上相邻项之间的分隔符。分隔符字符通常是逗号(,
)但也可能是其他原因:这取决于典型
设置数组的元素类型。在PostgreSQL发行版中提供的标准数据类型中,除了类型之外,所有数据类型都使用逗号盒
,它使用分号(;
).在多维数组中,每个维度(行、平面、立方体等)都有自己的花括号级别,并且必须在同一级别的相邻花括号实体之间写入分隔符。
如果元素值是空字符串、包含大括号、分隔符、双引号、反斜杠或空格,或者与单词匹配,那么数组输出例程将在元素值周围加双引号无效的
.元素值中嵌入的双引号和反斜杠将被反斜杠转义。对于数字数据类型,可以安全地假设永远不会出现双引号,但是对于文本数据类型,应该准备好处理引号的存在或不存在。
默认情况下,数组维度的下限索引值设置为1.为了用其他下限表示数组,可以在写入数组内容之前显式指定数组下标范围。这个装饰由方括号组成([]
)围绕每个数组维度的上下限,使用冒号(:
)中间的分隔符字符。数组维度装饰后面跟一个等号(=
).例如:
SELECT f1[1][-2][3] AS e1, f1[1][-1][5] AS e2
FROM (SELECT '[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int[] AS f1) AS ss;
e1 | e2
### Tip
The `ARRAY` constructor syntax (see [Section 4.2.12](sql-expressions.html#SQL-SYNTAX-ARRAY-CONSTRUCTORS)) is often easier to work with than the array-literal syntax when writing array values in SQL commands. In `ARRAY`, individual element values are written the same way they would be written when not members of an array.