Documentation PostgreSQL 8.0.25 | ||||
---|---|---|---|---|
Pr�c�dent | Arri�re rapide | Chapitre 8. Types de donn�es | Avance rapide | Suivant |
PostgreSQL autorise de d�finir des colonnes d'une table comme des tableaux multidimensionnels � longueur variable. Des tableaux de n'importe quel type, m�me d�fini par l'utilisateur, peuvent �tre cr��s. (N�anmoins, les tableaux de type composite ou de domaines ne sont pas encore support�s.)
Pour illustrer l'utilisation des types de tableaux, cr�ons cette table :
CREATE TABLE sal_emp ( nom text, paye_par_semaine integer[], planning text[][] );
Comme indiqu� ci-dessus, un type de donn�e tableau est nomm� en ajoutant des crochets ([]) au type de donn�e des �l�ments du tableau. La commande ci-dessus cr�era une table nomm�e sal_emp avec une colonne de type text (nom), un tableau � une dimension de type integer (paye_par_semaine), repr�sentant le salaire d'un employ� par semaine et un tableau � deux dimensions de type text (planning), repr�sentant le planning hebdomadaire de l'employ�.
La syntaxe pour CREATE TABLE permet de sp�cifier la taille exacte des tableaux, par exemple :
CREATE TABLE tictactoe ( carres integer[3][3] );
N�anmoins, l'impl�mentation actuelle n'oblige pas au respect des limites en taille du tableau -- le comportement est identique � celui des tableaux dont la longueur n'a pas �t� sp�cifi�e.
En fait, l'impl�mentation actuelle n'oblige pas non plus � d�clarer le nombre de dimensions. Les tableaux d'un type d'�l�ment particulier sont tous consid�r�s comme �tant du m�me type, sans v�rification de la taille ou du nombre de dimensions. Donc, d�clarer le nombre de dimensions ou la taille dans CREATE TABLE a uniquement un but de documentation, cela n'affecte pas le comportement lors de l'ex�cution.
Une syntaxe alternative, conforme au standard SQL:1999, pourrait �tre utilis�e pour les tableaux � une dimension. paye_par_semaine pourrait avoir �t� d�finie ainsi :
paye_par_semaine integer ARRAY[4],
Cette syntaxe n�cessite une constante de type entier pour indiquer la taille du tableau. N�anmoins, comme indiqu� pr�c�demment, PostgreSQL n'impose aucune restriction sur la taille.
Pour �crire une valeur de type tableau comme une constante litt�rale, encadrez les valeurs des �l�ments par des accolades et s�parez-les par des virgules. (Si vous connaissez le C, ce n'est pas diff�rent de la syntaxe C pour initialiser les structures.) Vous pouvez mettre des guillemets doubles autour des valeurs des �l�ments, et devez le faire si elles contiennent des virgules ou des accolades. (Plus de d�tails ci-dessous.) Le format g�n�ral d'une constante de type tableau est donc le suivant :
'{ val1 delim val2 delim ... }'
o� delim est le caract�re de d�limitation pour ce type, tel qu'il est enregistr� dans son entr�e pg_type. Parmi les types de donn�es standards fournis par la distribution PostgreSQL, le type box utilise un point-virgule (;) mais tous les autres utilisent une virgule (,). Chaque val est soit une constante du type des �l�ments du tableau ou un sous-tableau. Voici un exemple d'une constante tableau
'{{1,2,3},{4,5,6},{7,8,9}}'
Cette constante a deux dimensions, un tableau 3 par 3 consistant en trois sous-tableaux d'entiers.
(Ces types de constantes de tableau sont en fait un cas particulier des constantes de type g�n�rique abord�es dans la Section 4.1.2.5. La constante est trait�e initialement comme une cha�ne et pass�e � la routine de conversion d'entr�es de tableau. Une sp�cification explicite du type pourrait �tre n�cessaire.)
Maintenant, nous pouvons montrer quelques instructions INSERT.
INSERT INTO sal_emp VALUES ('Bill', '{10000, 10000, 10000, 10000}', '{{"rendez-vous", "repas"}, {}}'); INSERT INTO sal_emp VALUES ('Carol', '{20000, 25000, 25000, 25000}', '{{"rencontre", "repas"}, {"rencontre"}}'); ERROR: multidimensional arrays must have array expressions with matching dimensions
Notez que les tableaux � plusieurs dimensions doivent avoir des limites correspondantes pour chaque dimension. Une diff�rence provoque une erreur � l'ex�cution.
INSERT INTO sal_emp VALUES ('Bill', '{10000, 10000, 10000, 10000}', '{{"rencontre", "repas"}, {"entrainement", "pr�sentation"}}'); INSERT INTO sal_emp VALUES ('Carol', '{20000, 25000, 25000, 25000}', '{{"petit-d�jeuner", "consulting"}, {"rencontre", "repas"}}');
Une limitation de l'impl�mentation actuelle des tableaux existe, les �l�ments individuels d'un tableau ne peuvent avoir la valeur SQL NULL. Le tableau entier peut �tre NULL mais vous ne pouvez pas avoir des �l�ments NULL dans un tableau avec d'autres �l�ments non NULL. (Ceci est susceptible de changer dans le futur.)
Le r�sultat des deux insertions pr�c�dentes ressemble � ceci :
SELECT * FROM sal_emp; nom | paye_par_semaine | planning -------+---------------------------+-------------------- Bill | {10000,10000,10000,10000} | {{rencontre,repas},{entrainement,pr�sentation}} Carol | {20000,25000,25000,25000} | {{petit-d�jeuner,consulting},{rencontre,repas}} (2 rows)
La syntaxe du constructeur ARRAY peut aussi �tre utilis�e :
INSERT INTO sal_emp VALUES ('Bill', ARRAY[10000, 10000, 10000, 10000], ARRAY[['rendez-vous', 'repas'], ['entrainement','pr�sentation']]); INSERT INTO sal_emp VALUES ('Carol', ARRAY[20000, 25000, 25000, 25000], ARRAY[['petit-d�jeuner', 'consulting'], ['rencontre', 'repas']]);
Notez que les �l�ments du tableau sont des constantes SQL ordinaires ou des expressions ; par exemple, les cha�nes de caract�res litt�rales sont encadr�es par des guillemets simples au lieu de guillemets doubles comme cela serait le cas dans un tableau litt�ral. La syntaxe du constructeur ARRAY est discut�e plus en profondeur dans la Section 4.2.10.
Maintenant, nous pouvons lancer quelques requ�tes sur la table. Tout d'abord, montrons comment acc�der � un seul �l�ment du tableau � la fois. Cette requ�te retrouve le nom des employ�s dont la paye a chang� la deuxi�me semaine :
SELECT nom FROM sal_emp WHERE paye_par_semaine[1] <> paye_par_semaine[2]; nom ------- Carol (1 row)
Les nombres du tableau sont �crit entre crochets. Par d�faut, PostgreSQL utilise la convention des nombres commen�ant � 1 pour les tableaux, c'est-�-dire un tableau � n �l�ments commence avec array[1] et finit avec array[n].
Cette requ�te r�cup�re la paye de la troisi�me semaine pour tous les employ�s :
SELECT paye_par_semaine[3] FROM sal_emp; paye_par_semaine ------------------ 10000 25000 (2 rows)
Nous pouvons aussi acc�der � des parties rectangulaires arbitraires ou � des sous-tableaux. Une partie d'un tableau est not�e par l'�criture extr�mit� basse:extr�mit� haute quelle que soit la dimension des tableaux. Par exemple, cette requ�te retrouve le premier �l�ment du planning de Bill pour les deux premiers jours de la semaine :
SELECT planning[1:2][1:1] FROM sal_emp WHERE nom = 'Bill'; planning -------------------- {{rendez-vous},{entrainement}} (1 row)
Nous aurions aussi pu �crire
SELECT planning[1:2][1] FROM sal_emp WHERE nom = 'Bill';
en ayant le m�me r�sultat. Une op�ration d'indi�age de rang�e est toujours prise pour repr�senter une tranche de rang�e si un indice quelconque est �crit sous la forme inf�rieur:sup�rieur. Une limite basse de 1 est suppos�e pour toute tranche dont seule une valeur est sp�cifi�e. Voici un autre exemple :
SELECT planning[1:2][2] FROM sal_emp WHERE nom = 'Bill'; planning --------------------------- {{rendez-vous,repas},{entrainement,pr�sentation}} (1 row)
R�cup�rer en dehors des limites actuelles d'un tableau am�ne une valeur SQL NULL, pas une erreur. Par exemple, si planning a les dimensions [1:3][1:2], alors r�f�rencer planning[3][3] a un r�sultat NULL. De la m�me fa�on, une r�f�rence sur un tableau avec le mauvais nombre d'indices am�ne une valeur NULL plut�t qu'une erreur. R�cup�rer une partie d'un tableau compl�tement en dehors des limites actuelles renvoie un tableau NULL ; mais si la partie demand�e est partiellement int�gr�e aux limites du tableau, alors il est silencieusement r�duit � la r�gion d'intersection.
Les dimensions actuelles de toute valeur d'un tableau sont disponibles avec la
fonction array_dims
:
SELECT array_dims(planning) FROM sal_emp WHERE nom = 'Carol'; array_dims ------------ [1:2][1:2] (1 row)
array_dims
donne un r�sultat de type text,
ce qui est pratique � lire mais peut-�tre moins simple � interpr�ter pour les
programmes. Les dimensions sont aussi r�cup�rables avec
array_upper
et array_lower
, qui
renvoient respectivement la limite haute et basse d'un tableau sp�cifi�.
SELECT array_upper(planning, 1) FROM sal_emp WHERE nom = 'Carol'; array_upper ------------- 2 (1 row)
La valeur d'un tableau peut �tre compl�tement remplac�e :
UPDATE sal_emp SET paye_par_semaine = '{25000,25000,27000,27000}' WHERE nom = 'Carol';
ou en utilisant la syntaxe de l'expression ARRAY :
UPDATE sal_emp SET paye_par_semaine = ARRAY[25000,25000,27000,27000] WHERE nom = 'Carol';
On peut aussi mettre � jour un seul �l�ment d'un tableau :
UPDATE sal_emp SET paye_par_semaine[4] = 15000 WHERE nom = 'Bill';
ou faire une mise � jour par tranche :
UPDATE sal_emp SET paye_par_semaine[1:2] = '{27000,27000}' WHERE nom = 'Carol';
Une valeur de tableau enregistr�e peut �tre agrandie pour affecter un �l�ment adjacent � ceux d�j� pr�sents ou en affectant � une partie adjacente une partie des donn�es d�j� pr�sentes. Par exemple, si le tableau mon_tableau a pour le moment quatre �l�ments, il en aura cinq apr�s une mise � jour qui a affect� mon_tableau[5]. Actuellement, l'agrandissement de cette fa�on est seulement autoris� pour les tableaux � une dimension, et non pas pour les tableaux multidimensionnels.
L'affectation de parties d'un tableau permet la cr�ation de tableaux dont l'indice de d�part n'est pas 1. Par exemple, vous pourriez affecter mon_tableau[-2:7] pour cr�er un tableau avec les valeurs d'indices allant de -2 � 7.
Les valeurs de nouveaux tableaux peuvent aussi �tre construites en utilisant l'op�rateur de concat�nation, ||.
SELECT ARRAY[1,2] || ARRAY[3,4]; ?column? --------------- {1,2,3,4} (1 row) SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; ?column? --------------------- {{5,6},{1,2},{3,4}} (1 row)
L'op�rateur de concat�nation autorise un �l�ment � �tre plac� au d�but ou � la fin d'un tableau � une dimension. Il accepte aussi deux tableaux � N dimensions, ou un tableau � N dimensions et un � N+1 dimensions.
Lorsqu'un �l�ment seul est plac� au d�but d'un tableau � une dimension, le r�sultat est un tableau disposant d'une limite inf�rieure �gale � la limite inf�rieure de l'op�rande du c�t� droit moins un. Lorsqu'un �l�ment est plac� � la fin d'un tableau � une dimension, le r�sultat est un tableau contenant la limite inf�rieure de l'op�rande gauche. Par exemple :
SELECT array_dims(1 || ARRAY[2,3]); array_dims ------------ [0:2] (1 row) SELECT array_dims(ARRAY[1,2] || 3); array_dims ------------ [1:3] (1 row)
Lorsque deux tableaux ayant un m�me nombre de dimensions sont concat�n�s, le r�sultat conserve la limite inf�rieure de l'op�rande gauche. Le r�sultat est un tableau comprenant chaque �l�ment de l'op�rande gauche suivi de chaque �l�ment de l'op�rande droit. Par exemple :
SELECT array_dims(ARRAY[1,2] || ARRAY[3,4,5]); array_dims ------------ [1:5] (1 row) SELECT array_dims(ARRAY[[1,2],[3,4]] || ARRAY[[5,6],[7,8],[9,0]]); array_dims ------------ [1:5][1:2] (1 row)
Lorsqu'un tableau � N dimensions est plac� au d�but ou � la fin d'un tableau � N+1 dimensions, le r�sultat est analogue au cas ci-dessus. Chaque sous-tableau de dimension N est en quelque sorte un �l�ment de la dimension externe d'un tableau � N+1 dimensions. Par exemple :
SELECT array_dims(ARRAY[1,2] || ARRAY[[3,4],[5,6]]); array_dims ------------ [0:2][1:2] (1 row)
Un tableau peut aussi �tre construit en utilisant les fonctions
array_prepend
, array_append
ou array_cat
. Les deux premi�res supportent seulement les
tableaux � une dimension alors que array_cat
supporte les
tableaux multidimensionnels.
Notez que l'op�rateur de concat�nation vu ci-dessus est pr�f�r� �
l'utilisation directe de ces fonctions. En fait, les fonctions sont utilis�es
principalement pour l'impl�mentation de l'op�rateur de concat�nation.
N�anmoins, elles pourraient �tre directement utiles dans la cr�ation
d'agr�gats d�finis par l'utilisateur. Quelques exemples :
SELECT array_prepend(1, ARRAY[2,3]); array_prepend --------------- {1,2,3} (1 row) SELECT array_append(ARRAY[1,2], 3); array_append -------------- {1,2,3} (1 row) SELECT array_cat(ARRAY[1,2], ARRAY[3,4]); array_cat --------------- {1,2,3,4} (1 row) SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]); array_cat --------------------- {{1,2},{3,4},{5,6}} (1 row) SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]); array_cat --------------------- {{5,6},{1,2},{3,4}}
Pour rechercher une valeur dans un tableau, vous devez v�rifier chaque valeur dans le tableau. Ceci peut se faire � la main si vous connaissez la taille du tableau. Par exemple :
SELECT * FROM sal_emp WHERE paye_par_semaine[1] = 10000 OR paye_par_semaine[2] = 10000 OR paye_par_semaine[3] = 10000 OR paye_par_semaine[4] = 10000;
N�anmoins, ceci devient rapidement fastidieux pour les gros tableaux et n'est pas tr�s utile si la taille du tableau n'est pas connue. Une autre m�thode est d�crite dans Section 9.17. La requ�te ci-dessus est rempla�able par :
SELECT * FROM sal_emp WHERE 10000 = ANY (paye_par_semaine);
De plus, vous pouvez trouvez les lignes o� le tableau n'a que des valeurs �gales � 10000 avec :
SELECT * FROM sal_emp WHERE 10000 = ALL (paye_par_semaine);
Astuce�: Les tableaux ne sont pas toujours initialis�s ; rechercher des �l�ments sp�cifiques d'un tableau pourrait �tre un signe d'une mauvaise conception de la base de donn�es. Utilisez plut�t une table s�par�e avec une ligne pour chaque �l�ment faisant parti du tableau. Cela sera plus simple pour une recherche et fonctionnera mieux dans le cas d'un grand nombre d'�l�ments.
La repr�sentation externe du type texte d'une valeur d'un tableau consiste en des �l�ments interpr�t�s suivant les r�gles de conversion d'entr�es/sorties pour le type de l'�l�ment du tableau, plus des d�corations indiquant la structure du tableau. L'affichage consiste en des accolades ({ et }) autour des valeurs du tableau et des caract�res de d�limitation entre �l�ments adjacents. Le caract�re d�limiteur est habituellement une virgule (,) mais peut �tre autre chose : il est d�termin� par le param�tre typdelim du type de l'�l�ment tableau (parmi les types de donn�es standards support�s par l'impl�mentation de PostgreSQL, le type box utilise un point-virgule (;) mais tous les autres utilisent la virgule). Dans un tableau multidimensionnel, chaque dimension (row, plane, cube, etc.) utilise son propre niveau d'accolades et les d�limiteurs doivent �tre utilis�s entre des entit�s adjacentes au sein d'accolades de m�me niveau.
La routine de sortie du tableau placera des guillemets doubles autour des valeurs des �l�ments si elles sont des cha�nes vides ou contiennent des accolades, des caract�res d�limiteurs, des guillemets doubles, des antislash ou des espaces. Les guillemets doubles et les antislash int�gr�s aux valeurs des �l�ments seront �chapp�s avec un antislash. Pour les types de donn�es num�riques, on peut supposer sans risque que les doubles guillemets n'appara�tront jamais, mais pour les types de donn�es texte, vous devez vous pr�parer � g�rer la pr�sence et l'absence de guillemets. (Ceci est un changement du comportement � partir de la version pr�-7.2 de PostgreSQL.)
Par d�faut, la valeur de la limite basse d'un tableau est initialis�e � 1. Si une des dimensions du tableau a une limite basse diff�rente de 1, un affichage suppl�mentaire indiquant les dimensions r�elles du tableau pr�c�de l'affichage de la structure du tableau. Cet affichage consiste en des crochets ([]) autour de chaque limite basse et haute d'une dimension avec un d�limiteur deux-points (:) entre chaque. L'affichage des dimensions du tableau est suivie par un signe d'�galit� (=). Par exemple :
SELECT 1 || ARRAY[2,3] AS array; array --------------- [0:2]={1,2,3} (1 row) SELECT ARRAY[1,2] || ARRAY[[3,4]] AS array; array -------------------------- [0:1][1:2]={{1,2},{3,4}} (1 row)
Cette syntaxe peut aussi �tre utilis�e pour sp�cifier des indices de tableau diff�rents des indices par d�faut. Par exemple :
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 ----+---- 1 | 6 (1 row)
Comme indiqu� pr�c�demment, lors de l'�criture d'une valeur de tableau, vous pourriez �crire des guillemets doubles autour de chaque �l�ment individuel de tableau. Vous devez le faire si leur absence autour d'un �l�ment induit en erreur l'analyseur de la valeur du tableau. Par exemple, les �l�ments contenant des crochets, virgules (ou un caract�re d�limiteur), guillemets doubles, antislashs ou espace (en d�but comme en fin) doivent avoir des guillemets doubles. Pour placer un guillemet double ou un antislash dans une valeur d'�l�ment d'un tableau, faites-le pr�c�der d'un antislash. Autrement, vous pouvez �chapper tous les caract�res de donn�es qui sont utilis�s dans la syntaxe du tableau.
Vous pouvez ajouter des espaces avant un crochet gauche ou apr�s un crochet droit. Vous pouvez aussi ajouter des espaces avant tout �l�ment individuel. Dans tous les cas, les espaces seront ignor�s. Par contre, les espaces � l'int�rieur des �l�ments entre guillemets doubles ou entour�s par des caract�res autres que des espaces ne sont pas ignor�s.
Note�: Rappelez-vous que ce que vous �crivez comme commande SQL sera tout d'abord interpr�t� en tant que cha�ne litt�rale puis en tant que tableau. Ceci double le nombre d'antislash dont vous aurez besoin. Par exemple, pour ins�rer une valeur de tableau de type text contenant un antislash et un guillemet double, vous aurez besoin d'�crire
INSERT ... VALUES ('{"\\\\","\\""}');Le processeur de la cha�ne litt�rale supprime un niveau d'antislash, donc ce qui arrive � l'analyseur de tableau ressemble � {"\\","\""}. � la place, les cha�nes remplissant l'entr�e du type de donn�es text deviennent respectivement \ et ". (Si nous travaillions avec un type de donn�es dont la routine d'entr�e traitait aussi les antislash de mani�re sp�ciale, bytea par exemple, nous pourrions avoir besoin d'au plus huit antislash dans la commande pour en obtenir un dans l'�l�ment stock�.) Les guillemets dollar (voir Section 4.1.2.2) pourraient �tre utilis�s pour �viter le besoin des doubles antislashs.
Astuce�: La syntaxe du constructeur ARRAY (voir Section 4.2.10) est souvent plus facile � utiliser que la syntaxe du tableau litt�ral lors de l'�criture de valeurs du tableau en commandes SQL. Avec ARRAY, les valeurs de l'�l�ment individuel sont �crites de la m�me fa�on qu'elles auraient �t� �crites si elles n'avaient pas fait partie d'un tableau.
Pr�c�dent | Sommaire | Suivant |
Types champs de bits | Niveau sup�rieur | Types composites |