# 8.15.阵列

8.15.1. 数组类型的声明

8.15.2. 数组值输入

8.15.3. 访问阵列

8.15.4. 修改数组

8.15.5. 数组搜索

8.15.6. 数组输入和输出语法

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.