Postgres fournit des colonnes de table définies comme tables
multidimensionnelles de longeur variables. Des tableaux de chaque
type natif ou utilisateur peuvent être créés. Pour illustrer leur
utilisation, créons cette table :
CREATE TABLE sal_emp (
name text,
pay_by_quarter integer[],
schedule text[][]
); |
Comme indiqué, un type tableau est nommé par l'ajout de crochets
(
[]) au nom de type des éléments du tableau.
La requête ci-dessous créera une table nommée
sal_emp avec une chaîne
text
(
name), une table unidimensionnelle de type
integer (
pay_by_quarter),
qui représente le salaire des employés par trimestre, et un tableau
bidimensionnel de type
text
(
schedule), qui représente les horaires
hebdomadaires des employés.
Maintenant faisons quelques INSERT. Nous observons que
pour écrire une valeur tableau, nous insérons les valeurs des éléments
dans des crochets arrondis séparés par des virgules. Si vous connaissez
le langage C, ce n'est pas différent de la syntaxe d'initialisation
des 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"}}'); |
Maintenant, nous pouvons lancer certaines requêtes sur sal_emp.
En premier, nous voyons comment accéder à un élément unique d'un
tableau à un moment donné. Cette requête retrouve les noms des
employés dont la paie a changé au cours du second trimestre :
SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
name
-------
Carol
(1 row) |
Les nombres du tableau sont écrits dans des crochets carrés.
Postgres utilise la convention de numérotage
"à partir de 1"
pour les tableaux, qui donne, un tableau de
n éléments
démarre avec
array[1] et
fini avec
array[n].
Cette requête retrouve le troisième trimestre de paie de tous
les employés :
SELECT pay_by_quarter[3] FROM sal_emp;
pay_by_quarter
----------------
10000
25000
(2 rows) |
Nous pouvons aussi accéder à des coupes rectangulaires arbitraires
d'un tableau, ou sous-tableaux.
Une coupe de tableau est signifiée en écrivant des
indexage bas :
indexage haut pour une ou
plusieurs dimensions de tableau.
Cette requête retrouve la première rubrique de l'emploi du temps
de Bill pour les deux premiers jours de la semaine :
SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
schedule
--------------------
{{"meeting"},{""}}
(1 row) |
Nous pourrions aussi avoir écrit
SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill'; |
avec le même résultat. Une opération de sous-script de tableau
représente une coupe de tableau si certains des sous-scripts
sont écrits dans la forme
lower :
upper. Une limite basse de 1 est supposée
pour n'importe quel sous-script où seulement une valeur est spécifiée.
Une valeur de tableau peut être replacée complètement :
UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
WHERE name = 'Carol'; |
ou mise à jour pour un seul élément :
UPDATE sal_emp SET pay_by_quarter[4] = 15000
WHERE name = 'Bill'; |
ou mise à jour dans une coupe :
UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
WHERE name = 'Carol'; |
Un tableau peut être élargi en lui assignant un élément adjacent
à ceux déja présents, ou en lui assignant une coupe adjacente ou
chevauchant des données déjà présentes. Par exemple, si une valeur
de tableau possède 4 éléments, elle aura 5 éléments après une mise
à jour qui lui assigne array[5]. L'élargissement de cette manière
est admis seulement pour les tableaux unidimensionnels, pas
multidimensionnels.
La syntaxe de CREATE TABLE permet de définir des
tableaux de longueur fixe.
CREATE TABLE tictactoe (
squares integer[3][3]
); |
Cependant, la version courante ne précise pas les limites de
taille des tableaux --- le comportement est le même que pour les
tableaux de longueur non spécifiée.
Actuellement, cette version ne précise pas le nombre de dimensions
déclarées. Les tableaux d'un type particulier sont sont tous considérés
comme du même type, en regard de la taille ou du nombre des dimensions.
Les dimensions d'une valeur tableau peuvent être retrouvées par la
fonction array_dims :
SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol';
array_dims
------------
[1:2][1:1]
(1 row) |
array_dims produit un résultat
text,
qui est pratique à lire mais peut être pas pratique pour les programmes.
Pour chercher une valeur dans un tableau, vous devez vérifier chaque
valeur du tableau. Ceci peut être fait à la main (si vous connaissez
la taille du tableau) :
SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
pay_by_quarter[2] = 10000 OR
pay_by_quarter[3] = 10000 OR
pay_by_quarter[4] = 10000; |
Cependant celà devient rapidement pénible pour les gros tableaux, et
ce n'est pas pratique si la taille du tableau n'est pas connue.
Bien qu'elle ne fasse pas partie de la distribution normale de
Postgres, il existe une extension disponible qui définit de
nouveaux opérateurs et fonctions pour l'itération des valeurs
de tableaux. En les utilisant, la requête ci-dessous serait :
SELECT * FROM sal_emp WHERE pay_by_quarter[1:4] *= 10000; |
Pour rechercher sur le tableau entier (pas seulement les colonnes
spécifiées), vous pouvez utiliser :
SELECT * FROM sal_emp WHERE pay_by_quarter *= 10000; |
De plus, vous pouvez retrouver les lignes où le tableau a toutes
les valeurs égales à 10 000 avec :
SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000; |
Pour installer ce module optionnel, regardez dans le répertoire
contrib/array du source de Postgres.
 | Les tableaux ne sont pas placés; utiliser les tableaux de la
manière décrite précédemment est souvent un signe de mauvaise
conceptualisation de la base. Le champ tableau serait généralement
disposé dans une table séparée. Évidemment les tables peuvent être
questionnées facilement.
|
 | Une limitation à l'implémentation actuelle des tableaux est que
les éléments individuels d'un tableau ne peuvent ne peuvent être
NULL en SQL. Le tableau entier peut être placé à NULL, mais vous ne
pouvez avoir un tableau avec certains éléments NULL et certains non.
La correction de ceci est dans la liste des choses "à faire".
|
 | Souvenez vous que quoi que vous écriviez dans une requête SQL elle
sera d'abord interprétée comme une chaîne littérale, et ensuite comme
un tableau. Ceci double le nombre de backslashes dont vous avez besoin.
Par exemple, pour insérer une valeur tableau text contenant un backslash
et un guillemet, vous devez écrire :
INSERT ... VALUES ('{"\\\\","\\""}'); |
Le processeur de chaîne efface un niveau de backslashes, ce qui
se produit pour le parser de la valeur tableau comme
{"\\","\""}.
Les chaînes fédèrent les routines d'entrée de type text devenant
\ et " respectivement. (Si vous travaillez
avec un type dont la routine d'entrée traite aussi les backslashes
de façon spéciale, bytea par exemple, vous aurez besoin de plus de 8
backslashes dans la requête pour obtenir qu'un backslash soit ainsi
stocké dans l'élément tableau).
|