Valeurs non-atomiques

L'un des principes du modèle relationnel est que les attributs d'une relation sont atomiques. Postgres n'a pas pas cette restriction; les attributs peuvent eux mêmes contenir des sous-valeurs accessibles depuis le langage de requête. Par exemple, vous pouvez créer des attributs qui sont des tableaux de types de base.

Tableaux

Postgres admet que les attributs d'une instance soient définis comme des tableaux de longueur fixe ou non. Des tableaux d'un type base ou d'un type défini par l'utilisateur peuvent être créés. Pour illustrer leur usage, nous créerons une classe avec des tableaux de type base.
CREATE TABLE SAL_EMP (
    name            text,
    pay_by_quarter  int4[],
    schedule        text[][]
);

La requête ci-dessous créera une classe nommée SAL_EMP avec une chaîne (nom) text, un tableau mono-dimensionnel de int4(pay_by_quarter), qui représente les salaires trimestriels des employés et un tableau bi-dimensionnel de text (schedule) qui contient leurs horaires hebdomadaires. Maintenant nous faisons quelques INSERT; notez que quand nous voulons un tableau nous incluons les valeurs entre accolades et les séparons par des virgules. Si vous connaissez le C, ce n'est pas très différent au niveau syntaxe pour initialiser les structures.
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"}}');
Par défaut Postgres indice les tableaux à partir de 1 (one-based) : un tableau de n éléments commence donc avec l'élément tableau[1] et finit avec tableau [n].

Nous pouvons lancer certaines requêtes sur SAL_EMP. En premier, nous montrons comment accéder à un élément unique d'un rang à un moment donné. Cette requête retrouve les noms des employés dont la paie a changé au second trimestre :
SELECT name
    FROM SAL_EMP
    WHERE SAL_EMP.pay_by_quarter[1] <>
    SAL_EMP.pay_by_quarter[2];

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

Cette requête retrouve la paie du troisième trimestre des tous les employés :
SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP;


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

Nous pouvons aussi accéder arbitrairement à des tranches, ou sous-rang. Cette requête retrouve le premier article sur l'agenda de Bill pour les deux premiers jours de la semaine.
SELECT SAL_EMP.schedule[1:2][1:1]
    FROM SAL_EMP
    WHERE SAL_EMP.name = 'Bill';

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