5.2. 非原子数值

关系型模型的一个要求就是所有关系的字段都是原子化的. Postgres 没有这个限制; 字段可以有自己的子值,这些值可以通过查询语言访问. 例如,你可以创建数组类字段.

5.2.1. 数组

Postgres 允许一个字段被定义成定长或不定长的多维数组. 数组可以是任何基本类型或者用户自定义的类型. 为说明这些,我们先创建一个由基本类型数组组成的表.

CREATE TABLE SAL_EMP (
    name            text,
    pay_by_quarter  integer[],
    schedule        text[][]
);
     

上面的查询语句将创建一个叫 SAL_EMP的表,表中有一个 text 串(name),一个 integer 型的一维数组(pay_by_quarter), 代表以季度为单位的雇员薪水和一个二维的 text 型数组(schedule),代表雇员的周计划. 现在我们做一些 INSERTS;注意当我们向数组中追加数据时, 我们用花括号将数据括起来,并且用逗号将它们区别开.如果你懂 C,那么这和初始化一个结构的语法很像.

INSERT INTO SAL_EMP
    VALUES ('Bill',
    '{10000, 10000, 10000, 10000}',
    '{{"meeting", "lunch"}, {}}');

INSERT INTO SAL_EMP
    VALUES ('Carol',
    '{20000, 25000, 25000, 25000}',
    '{{"talk", "consult"}, {"meeting"}}');
     
Postgres 缺省使用 "1为基" 的数组(脚标)计数方法, 也就是说,一个 n 个元素的数组第一个元素是array[1], 最后一个元素是array[n].现在, 我们在 SAL_EMP 表上运行一些查询.首先, 我们展示如何一次访问一个数组的某一元素. 这个查询检索出在第二季度收入改变了的雇员名:
SELECT name
    FROM SAL_EMP
    WHERE SAL_EMP.pay_by_quarter[1] <>
    SAL_EMP.pay_by_quarter[2];

+------+
|name  |
+------+
|Carol |
+------+
     

下面的查询检索所有雇员第三季度的收入:

SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;


+---------------+
|pay_by_quarter |
+---------------+
|10000          |
+---------------+
|25000          |
+---------------+
     

我们还可以访问数组任意片段或者子数组. 下面查询检索 Bill 周计划头两天的第一项.

SELECT SAL_EMP.schedule[1:2][1:1]
    FROM SAL_EMP
    WHERE SAL_EMP.name = 'Bill';

+-------------------+
|schedule           |
+-------------------+
|{{"meeting"},{""}} |
+-------------------+