| 1 |
<!-- $Header: /var/lib/cvs/pgsql-fr/sgml/array.sgml,v 1.9.2.2 2005/07/15 06:33:35 guillaume Exp $ --> |
|---|
| 2 |
|
|---|
| 3 |
<sect1 id="arrays"> |
|---|
| 4 |
<title>Tableaux</title> |
|---|
| 5 |
|
|---|
| 6 |
<indexterm> |
|---|
| 7 |
<primary>tableau</primary> |
|---|
| 8 |
<secondary>array</secondary> |
|---|
| 9 |
</indexterm> |
|---|
| 10 |
|
|---|
| 11 |
<para> |
|---|
| 12 |
<productname>PostgreSQL</productname> autorise que des colonnes d'une table |
|---|
| 13 |
soient définies en tant que tableaux multidimensionnels à longueur variable. |
|---|
| 14 |
Des tableaux de n'importe quel type, même défini par l'utilisateur, peuvent |
|---|
| 15 |
être créés. |
|---|
| 16 |
</para> |
|---|
| 17 |
|
|---|
| 18 |
<sect2> |
|---|
| 19 |
<title>Déclaration des types de tableaux</title> |
|---|
| 20 |
|
|---|
| 21 |
<para> |
|---|
| 22 |
Pour illustrer l'utilisation des types de tableaux, créons cette table : |
|---|
| 23 |
<programlisting> |
|---|
| 24 |
CREATE TABLE sal_emp ( |
|---|
| 25 |
nom text, |
|---|
| 26 |
paye_par_semaine integer[], |
|---|
| 27 |
planning text[][] |
|---|
| 28 |
); |
|---|
| 29 |
</programlisting> |
|---|
| 30 |
Comme indiqué ci-dessus, un type de donnée tableau est nommé en ajoutant des |
|---|
| 31 |
crochets (<literal>[]</>) au type de données des éléments du tableau. La |
|---|
| 32 |
commande ci-dessus créera une table nommée <structname>sal_emp</structname> |
|---|
| 33 |
avec une colonne de type <type>text</type> (<structfield>nom</structfield>), |
|---|
| 34 |
un tableau à une dimension de type <type>integer</type> |
|---|
| 35 |
(<structfield>paye_par_semaine</structfield>), représentant le salaire d'un |
|---|
| 36 |
employé par semaine et un tableau à deux dimensions de type |
|---|
| 37 |
<type>text</type> (<structfield>planning</structfield>), représentant le |
|---|
| 38 |
planning hebdomadaire de l'employé. |
|---|
| 39 |
</para> |
|---|
| 40 |
|
|---|
| 41 |
<para> |
|---|
| 42 |
La syntaxe pour <command>CREATE TABLE</command> permet de spécifier la taille |
|---|
| 43 |
exacte des tableaux, par exemple : |
|---|
| 44 |
|
|---|
| 45 |
<programlisting> |
|---|
| 46 |
CREATE TABLE tictactoe ( |
|---|
| 47 |
carres integer[3][3] |
|---|
| 48 |
); |
|---|
| 49 |
</programlisting> |
|---|
| 50 |
|
|---|
| 51 |
Néanmoins, l'implémentation actuelle n'oblige pas au respect des limites en |
|---|
| 52 |
taille du tableau -- le comportement est identique à celui des tableaux dont |
|---|
| 53 |
la longueur n'a pas été spécifiée. |
|---|
| 54 |
</para> |
|---|
| 55 |
|
|---|
| 56 |
<para> |
|---|
| 57 |
En fait, l'implémentation actuelle n'oblige pas non plus à déclarer le |
|---|
| 58 |
nombre de dimensions. Les tableaux d'un type d'élément particulier sont tous |
|---|
| 59 |
considérés comme étant du même type, sans vérification de la taille ou du nombre de |
|---|
| 60 |
dimensions. Donc, déclarer le nombre de dimensions ou la taille dans |
|---|
| 61 |
<command>CREATE TABLE</command> a uniquement un but de documentation, cela |
|---|
| 62 |
n'affecte pas le comportement lors de l'exécution. |
|---|
| 63 |
</para> |
|---|
| 64 |
|
|---|
| 65 |
<para> |
|---|
| 66 |
Une syntaxe alternative, conforme au standard SQL99, pourrait être |
|---|
| 67 |
utilisée pour les tableaux à une dimension. |
|---|
| 68 |
<structfield>paye_par_semaine</structfield> pourrait avoir été définie ainsi : |
|---|
| 69 |
<programlisting> |
|---|
| 70 |
paye_par_semaine integer ARRAY[4], |
|---|
| 71 |
</programlisting> |
|---|
| 72 |
Cette syntaxe nécessite une constante de type entier pour indiquer la taille |
|---|
| 73 |
du tableau. Néanmoins, comme indiqué précédemment, <productname>PostgreSQL</> |
|---|
| 74 |
n'impose aucune restriction sur la taille. |
|---|
| 75 |
</para> |
|---|
| 76 |
</sect2> |
|---|
| 77 |
|
|---|
| 78 |
<sect2> |
|---|
| 79 |
<title>Saisie de valeurs de type tableau</title> |
|---|
| 80 |
|
|---|
| 81 |
<indexterm> |
|---|
| 82 |
<primary>tableau</primary> |
|---|
| 83 |
<secondary>constante</secondary> |
|---|
| 84 |
</indexterm> |
|---|
| 85 |
|
|---|
| 86 |
<para> |
|---|
| 87 |
Pour écrire une valeur de type tableau comme une constante littérale, |
|---|
| 88 |
encadrez les valeurs des éléments par des accolades et séparez-les par des |
|---|
| 89 |
virgules. (Si vous connaissez le C, ce n'est pas différent de la syntaxe C |
|---|
| 90 |
pour initialiser les structures.) Vous pouvez mettre des guillemets doubles |
|---|
| 91 |
autour des valeurs des éléments et, en fait, vous devez le faire si elles |
|---|
| 92 |
contiennent des virgules ou des accolades. (Plus de détails ci-dessous.) |
|---|
| 93 |
Donc, le format général d'une constante de type tableau est la |
|---|
| 94 |
suivante : |
|---|
| 95 |
<synopsis> |
|---|
| 96 |
'{ <replaceable>val1</replaceable> <replaceable>delim</replaceable> <replaceable>val2</replaceable> <replaceable>delim</replaceable> ... }' |
|---|
| 97 |
</synopsis> |
|---|
| 98 |
où <replaceable>delim</replaceable> est le caractère de délimitation pour ce |
|---|
| 99 |
type, tel qu'il est enregistré dans son entrée <literal>pg_type</literal>. |
|---|
| 100 |
(Pour tous les types intégrés, il s'agit du caractère virgule |
|---|
| 101 |
<quote><literal>,</literal></>.) Chaque |
|---|
| 102 |
<replaceable>val</replaceable> est soit une constante du tableau soit un |
|---|
| 103 |
sous-tableau. Voici un exemple d'une constante tableau |
|---|
| 104 |
<programlisting> |
|---|
| 105 |
'{{1,2,3},{4,5,6},{7,8,9}}' |
|---|
| 106 |
</programlisting> |
|---|
| 107 |
Cette constante a deux dimensions, un tableau 3 par 3 consistant en trois |
|---|
| 108 |
sous-tableaux d'entiers. |
|---|
| 109 |
</para> |
|---|
| 110 |
|
|---|
| 111 |
<para> |
|---|
| 112 |
(Ces types de constantes de tableau sont actuellement le seul cas spécifique |
|---|
| 113 |
de constantes de type générique discutés dans la <xref |
|---|
| 114 |
linkend="sql-syntax-constants-generic">. La constante est traitée |
|---|
| 115 |
initialement comme une chaîne et passée à la routine de conversion d'entrées |
|---|
| 116 |
de tableau. Une spécification explicite du type pourrait être nécessaire.) |
|---|
| 117 |
</para> |
|---|
| 118 |
|
|---|
| 119 |
<para> |
|---|
| 120 |
Maintenant, nous pouvons montrer quelques instructions |
|---|
| 121 |
<command>INSERT</command>. |
|---|
| 122 |
|
|---|
| 123 |
<programlisting> |
|---|
| 124 |
INSERT INTO sal_emp |
|---|
| 125 |
VALUES ('Bill', |
|---|
| 126 |
'{10000, 10000, 10000, 10000}', |
|---|
| 127 |
'{{"rendez-vous", "repas"}, {}}'); |
|---|
| 128 |
|
|---|
| 129 |
INSERT INTO sal_emp |
|---|
| 130 |
VALUES ('Carol', |
|---|
| 131 |
'{20000, 25000, 25000, 25000}', |
|---|
| 132 |
'{{"conférence", "consultation"}, {"rencontre"}}'); |
|---|
| 133 |
</programlisting> |
|---|
| 134 |
</para> |
|---|
| 135 |
|
|---|
| 136 |
<para> |
|---|
| 137 |
Une limitation de l'implémentation actuelle des tableaux est que les éléments |
|---|
| 138 |
individuels d'un tableau ne peuvent avoir la valeur SQL NULL. Le tableau |
|---|
| 139 |
entier peut être NULL mais vous ne pouvez pas avoir des éléments NULL dans |
|---|
| 140 |
un tableau avec d'autres éléments non NULL. |
|---|
| 141 |
</para> |
|---|
| 142 |
|
|---|
| 143 |
<para> |
|---|
| 144 |
Ceci peut amener des résultats surprenants. Par exemple, le résultat des deux |
|---|
| 145 |
insertions précédentes ressemble à ceci : |
|---|
| 146 |
<programlisting> |
|---|
| 147 |
SELECT * FROM sal_emp; |
|---|
| 148 |
nom | paye_par_semaine | planning |
|---|
| 149 |
-------+---------------------------+-------------------- |
|---|
| 150 |
Bill | {10000,10000,10000,10000} | {{rendez-vous},{""}} |
|---|
| 151 |
Carol | {20000,25000,25000,25000} | {{conférence},{rencontre}} |
|---|
| 152 |
(2 rows) |
|---|
| 153 |
</programlisting> |
|---|
| 154 |
Parce que l'élément <literal>[2][2]</literal> de |
|---|
| 155 |
<structfield>planning</structfield> est manquant dans chaque instruction |
|---|
| 156 |
<command>INSERT</command>, l'élément <literal>[1][2]</literal> est annulé. |
|---|
| 157 |
</para> |
|---|
| 158 |
|
|---|
| 159 |
<note> |
|---|
| 160 |
<para> |
|---|
| 161 |
Corriger ceci est dans la liste des points à règler. |
|---|
| 162 |
</para> |
|---|
| 163 |
</note> |
|---|
| 164 |
|
|---|
| 165 |
<para> |
|---|
| 166 |
La syntaxe de l'expression <literal>ARRAY</literal> pourrait aussi être |
|---|
| 167 |
utilisée : |
|---|
| 168 |
<programlisting> |
|---|
| 169 |
INSERT INTO sal_emp |
|---|
| 170 |
VALUES ('Bill', |
|---|
| 171 |
ARRAY[10000, 10000, 10000, 10000], |
|---|
| 172 |
ARRAY[['rendez-vous', 'repas'], ['','']]); |
|---|
| 173 |
|
|---|
| 174 |
INSERT INTO sal_emp |
|---|
| 175 |
VALUES ('Carol', |
|---|
| 176 |
ARRAY[20000, 25000, 25000, 25000], |
|---|
| 177 |
ARRAY[['conférence', 'consultation'], ['rencontre', '']]); |
|---|
| 178 |
SELECT * FROM sal_emp; |
|---|
| 179 |
nom | paye_par_semaine | planning |
|---|
| 180 |
-------+---------------------------+------------------------------- |
|---|
| 181 |
Bill | {10000,10000,10000,10000} | {{rendez-vous,repas},{"",""}} |
|---|
| 182 |
Carol | {20000,25000,25000,25000} | {{conférence,consultation},{rencontre,""}} |
|---|
| 183 |
(2 rows) |
|---|
| 184 |
</programlisting> |
|---|
| 185 |
Notez qu'avec cette syntaxe, les tableaux multidimensionels doivent |
|---|
| 186 |
correspondre parfaitement pour chaque dimension. Sans correspondance, un |
|---|
| 187 |
rapport d'erreur apparaît, plutôt que d'oublier silencieusement les valeurs |
|---|
| 188 |
comme dans le cas précédent. Par exemple : |
|---|
| 189 |
<programlisting> |
|---|
| 190 |
INSERT INTO sal_emp |
|---|
| 191 |
VALUES ('Carol', |
|---|
| 192 |
ARRAY[20000, 25000, 25000, 25000], |
|---|
| 193 |
ARRAY[['conférence', 'consultation'], ['rencontre']]); |
|---|
| 194 |
ERROR: multidimensional arrays must have array expressions with matching dimensions |
|---|
| 195 |
</programlisting> |
|---|
| 196 |
Notez aussi que les éléments du tableau sont des constantes SQL ordinaires ou |
|---|
| 197 |
des expressions ; par exemple, les chaînes de caractères littérales sont |
|---|
| 198 |
encadrées par des guillemets simples au lieu de guillemets doubles comme cela |
|---|
| 199 |
serait le cas dans un tableau littéral. La syntaxe d'expression |
|---|
| 200 |
<literal>ARRAY</> est discutée plus en profondeur dans la <xref |
|---|
| 201 |
linkend="sql-syntax-array-constructors">. |
|---|
| 202 |
</para> |
|---|
| 203 |
|
|---|
| 204 |
</sect2> |
|---|
| 205 |
|
|---|
| 206 |
<sect2> |
|---|
| 207 |
<title>Accès aux tableaux</title> |
|---|
| 208 |
|
|---|
| 209 |
<para> |
|---|
| 210 |
Maintenant, nous pouvons lancer quelques requêtes sur la table. Tout d'abord, |
|---|
| 211 |
montrons comment accéder à un seul élément du tableau à la fois. Cette |
|---|
| 212 |
requête retrouve le nom des employés dont la paye a changé la deuxième |
|---|
| 213 |
semaine : |
|---|
| 214 |
|
|---|
| 215 |
<programlisting> |
|---|
| 216 |
SELECT nom FROM sal_emp WHERE paye_par_semaine[1] <> paye_par_semaine[2]; |
|---|
| 217 |
|
|---|
| 218 |
nom |
|---|
| 219 |
------- |
|---|
| 220 |
Carol |
|---|
| 221 |
(1 row) |
|---|
| 222 |
</programlisting> |
|---|
| 223 |
|
|---|
| 224 |
Les nombres du tableau sont écrit entre crochets. Par défaut, |
|---|
| 225 |
<productname>PostgreSQL</productname> utilise la convention des nombres |
|---|
| 226 |
commençant à 1 pour les tableaux, c'est-à-dire un tableau à |
|---|
| 227 |
<replaceable>n</> éléments commence avec <literal>array[1]</literal> et finit |
|---|
| 228 |
avec <literal>array[<replaceable>n</>]</literal>. |
|---|
| 229 |
</para> |
|---|
| 230 |
|
|---|
| 231 |
<para> |
|---|
| 232 |
Cette requête retrouve la paye de la troisième semaine pour tous les employés : |
|---|
| 233 |
|
|---|
| 234 |
<programlisting> |
|---|
| 235 |
SELECT paye_par_semaine[3] FROM sal_emp; |
|---|
| 236 |
|
|---|
| 237 |
paye_par_semaine |
|---|
| 238 |
------------------ |
|---|
| 239 |
10000 |
|---|
| 240 |
25000 |
|---|
| 241 |
(2 rows) |
|---|
| 242 |
</programlisting> |
|---|
| 243 |
</para> |
|---|
| 244 |
|
|---|
| 245 |
<para> |
|---|
| 246 |
Nous pouvons aussi accéder à des parties rectangulaires arbitraires ou à des |
|---|
| 247 |
sous-tableaux. Une partie d'un tableau est notée par l'écriture |
|---|
| 248 |
<literal><replaceable>extrémité basse</replaceable>:<replaceable>extrémité haute</replaceable></literal> |
|---|
| 249 |
quelque soit la dimension des tableaux. Par exemple, cette requête retrouve |
|---|
| 250 |
le premier élément du planning de Bill pour les deux premiers jours de la |
|---|
| 251 |
semaine : |
|---|
| 252 |
|
|---|
| 253 |
<programlisting> |
|---|
| 254 |
SELECT planning[1:2][1:1] FROM sal_emp WHERE nom = 'Bill'; |
|---|
| 255 |
|
|---|
| 256 |
planning |
|---|
| 257 |
-------------------- |
|---|
| 258 |
{{rendez-vous},{""}} |
|---|
| 259 |
(1 row) |
|---|
| 260 |
</programlisting> |
|---|
| 261 |
|
|---|
| 262 |
Nous aurions aussi pu écrire |
|---|
| 263 |
|
|---|
| 264 |
<programlisting> |
|---|
| 265 |
SELECT planning[1:2][1] FROM sal_emp WHERE nom = 'Bill'; |
|---|
| 266 |
</programlisting> |
|---|
| 267 |
|
|---|
| 268 |
en ayant le même résultat. Une opération d'indiçage de rangée est toujours |
|---|
| 269 |
prise pour représenter une tranche de rangée si un indice quelconque est |
|---|
| 270 |
écrit sous la forme |
|---|
| 271 |
<literal><replaceable>inférieur</replaceable>:<replaceable>supérieur</replaceable></literal>. |
|---|
| 272 |
Une limite basse de 1 est supposée pour toute tranche dont seule une valeur |
|---|
| 273 |
est spécifiée. Voici un autre exemple : |
|---|
| 274 |
<programlisting> |
|---|
| 275 |
SELECT planning[1:2][2] FROM sal_emp WHERE nom = 'Bill'; |
|---|
| 276 |
planning |
|---|
| 277 |
--------------------------- |
|---|
| 278 |
{{rendez-vous,repas},{"",""}} |
|---|
| 279 |
(1 row) |
|---|
| 280 |
</programlisting> |
|---|
| 281 |
</para> |
|---|
| 282 |
|
|---|
| 283 |
<para> |
|---|
| 284 |
Les dimensions actuelles de toute valeur d'un tableau sont disponibles avec la fonction |
|---|
| 285 |
<function>array_dims</function> : |
|---|
| 286 |
|
|---|
| 287 |
<programlisting> |
|---|
| 288 |
SELECT array_dims(planning) FROM sal_emp WHERE nom = 'Carol'; |
|---|
| 289 |
|
|---|
| 290 |
array_dims |
|---|
| 291 |
------------ |
|---|
| 292 |
[1:2][1:1] |
|---|
| 293 |
(1 row) |
|---|
| 294 |
</programlisting> |
|---|
| 295 |
|
|---|
| 296 |
<function>array_dims</function> donne un résultat de type <type>text</type>, |
|---|
| 297 |
ce qui est agréable à lire mais peut-être moins simple à interpréter pour les programmes. |
|---|
| 298 |
Les dimensions sont aussi récupérables avec <function>array_upper</function> |
|---|
| 299 |
et <function>array_lower</function>, qui renvoient respectivement la limite |
|---|
| 300 |
haute et basse d'un tableau spécifié. |
|---|
| 301 |
|
|---|
| 302 |
<programlisting> |
|---|
| 303 |
SELECT array_upper(planning, 1) FROM sal_emp WHERE nom = 'Carol'; |
|---|
| 304 |
|
|---|
| 305 |
array_upper |
|---|
| 306 |
------------- |
|---|
| 307 |
2 |
|---|
| 308 |
(1 row) |
|---|
| 309 |
</programlisting> |
|---|
| 310 |
</para> |
|---|
| 311 |
</sect2> |
|---|
| 312 |
|
|---|
| 313 |
<sect2> |
|---|
| 314 |
<title>Modification de tableaux</title> |
|---|
| 315 |
|
|---|
| 316 |
<para> |
|---|
| 317 |
La valeur d'un tableau peut être complètement remplacée : |
|---|
| 318 |
|
|---|
| 319 |
<programlisting> |
|---|
| 320 |
UPDATE sal_emp SET paye_par_semaine = '{25000,25000,27000,27000}' |
|---|
| 321 |
WHERE nom = 'Carol'; |
|---|
| 322 |
</programlisting> |
|---|
| 323 |
|
|---|
| 324 |
ou en utilisant la syntaxe de l'expression <literal>ARRAY</literal> : |
|---|
| 325 |
|
|---|
| 326 |
<programlisting> |
|---|
| 327 |
UPDATE sal_emp SET paye_par_semaine = ARRAY[25000,25000,27000,27000] |
|---|
| 328 |
WHERE nom = 'Carol'; |
|---|
| 329 |
</programlisting> |
|---|
| 330 |
|
|---|
| 331 |
Un tableau peut aussi être mis à jour pour un seul élément : |
|---|
| 332 |
|
|---|
| 333 |
<programlisting> |
|---|
| 334 |
UPDATE sal_emp SET paye_par_semaine[4] = 15000 |
|---|
| 335 |
WHERE nom = 'Bill'; |
|---|
| 336 |
</programListing> |
|---|
| 337 |
|
|---|
| 338 |
ou mise à jour par tranche : |
|---|
| 339 |
|
|---|
| 340 |
<programlisting> |
|---|
| 341 |
UPDATE sal_emp SET paye_par_semaine[1:2] = '{27000,27000}' |
|---|
| 342 |
WHERE nom = 'Carol'; |
|---|
| 343 |
</programlisting> |
|---|
| 344 |
|
|---|
| 345 |
</para> |
|---|
| 346 |
|
|---|
| 347 |
<para> |
|---|
| 348 |
Une valeur de tableau enregistrée peut être agrandie pour affecter un élément |
|---|
| 349 |
adjacent à ceux déjà présents ou en affectant à une partie adjacente |
|---|
| 350 |
une partie des données déjà présentes. Par exemple, si le tableau |
|---|
| 351 |
<literal>montableau</> a actuellement quatre éléments, il en aura cinq après |
|---|
| 352 |
une mise à jour qui a affecté <literal>montableau[5]</>. Actuellement, |
|---|
| 353 |
l'agrandissement de cette façon est seulement autorisé pour les tableaux à |
|---|
| 354 |
une dimension, et non pas pour les tableaux multidimensionnels. |
|---|
| 355 |
</para> |
|---|
| 356 |
|
|---|
| 357 |
<para> |
|---|
| 358 |
L'affectation de parties d'un tableau permet la création de tableaux |
|---|
| 359 |
n'utilisant pas d'indice inférieur. Par exemple, vous pourriez affecter |
|---|
| 360 |
<literal>montableau[-2:7]</> pour créer un tableau avec les valeurs d'indices |
|---|
| 361 |
inférieurs allant de -2 à 7. |
|---|
| 362 |
</para> |
|---|
| 363 |
|
|---|
| 364 |
<para> |
|---|
| 365 |
Les valeurs de nouveaux tableaux peuvent aussi être construites en utilisant |
|---|
| 366 |
l'opérateur de concaténation, |
|---|
| 367 |
<literal>||</literal>. |
|---|
| 368 |
<programlisting> |
|---|
| 369 |
SELECT ARRAY[1,2] || ARRAY[3,4]; |
|---|
| 370 |
?column? |
|---|
| 371 |
--------------- |
|---|
| 372 |
{1,2,3,4} |
|---|
| 373 |
(1 row) |
|---|
| 374 |
|
|---|
| 375 |
SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; |
|---|
| 376 |
?column? |
|---|
| 377 |
--------------------- |
|---|
| 378 |
{{5,6},{1,2},{3,4}} |
|---|
| 379 |
(1 row) |
|---|
| 380 |
</programlisting> |
|---|
| 381 |
</para> |
|---|
| 382 |
|
|---|
| 383 |
<para> |
|---|
| 384 |
L'opérateur de concaténation autorise un élément à être placé au début ou à |
|---|
| 385 |
la fin d'un tableau à une dimension. Il accepte aussi deux tableaux à |
|---|
| 386 |
<replaceable>N</> dimensions, ou un tableau à <replaceable>N</> dimensions |
|---|
| 387 |
et un à <replaceable>N+1</> dimensions. |
|---|
| 388 |
</para> |
|---|
| 389 |
|
|---|
| 390 |
<para> |
|---|
| 391 |
Lorsqu'un seul élément est placé au début d'un tableau à une dimension, le |
|---|
| 392 |
résultat est un tableau disposant d'une limite inférieure égale à la limite |
|---|
| 393 |
inférieure de l'opérande du côté droit moins un. Lorsqu'un élément est placé |
|---|
| 394 |
à la fin d'un tableau à une dimension, le résultat est un tableau contenant la |
|---|
| 395 |
limite inférieure de l'opérande gauche. Par exemple : |
|---|
| 396 |
<programlisting> |
|---|
| 397 |
SELECT array_dims(1 || ARRAY[2,3]); |
|---|
| 398 |
array_dims |
|---|
| 399 |
------------ |
|---|
| 400 |
[0:2] |
|---|
| 401 |
(1 row) |
|---|
| 402 |
|
|---|
| 403 |
SELECT array_dims(ARRAY[1,2] || 3); |
|---|
| 404 |
array_dims |
|---|
| 405 |
------------ |
|---|
| 406 |
[1:3] |
|---|
| 407 |
(1 row) |
|---|
| 408 |
</programlisting> |
|---|
| 409 |
</para> |
|---|
| 410 |
|
|---|
| 411 |
<para> |
|---|
| 412 |
Lorsque deux tableaux ayant un même nombre de dimensions sont concaténés, le |
|---|
| 413 |
résultat conserve la limite inférieure de l'opérande gauche. Le résultat est |
|---|
| 414 |
un tableau comprenant chaque élément de l'opérande gauche suivi de chaque |
|---|
| 415 |
élément de l'opérande droit. Par exemple : |
|---|
| 416 |
<programlisting> |
|---|
| 417 |
SELECT array_dims(ARRAY[1,2] || ARRAY[3,4,5]); |
|---|
| 418 |
array_dims |
|---|
| 419 |
------------ |
|---|
| 420 |
[1:5] |
|---|
| 421 |
(1 row) |
|---|
| 422 |
|
|---|
| 423 |
SELECT array_dims(ARRAY[[1,2],[3,4]] || ARRAY[[5,6],[7,8],[9,0]]); |
|---|
| 424 |
array_dims |
|---|
| 425 |
------------ |
|---|
| 426 |
[1:5][1:2] |
|---|
| 427 |
(1 row) |
|---|
| 428 |
</programlisting> |
|---|
| 429 |
</para> |
|---|
| 430 |
|
|---|
| 431 |
<para> |
|---|
| 432 |
Lorsqu'un tableau à <replaceable>N</> dimensions est placé au début ou à la |
|---|
| 433 |
fin d'un tableau à <replaceable>N+1</> dimensions, le résultat est analogue au |
|---|
| 434 |
cas ci-dessus. Chaque sous-tableau de dimension <replaceable>N</> est en |
|---|
| 435 |
quelque sorte un élément de la dimension externe d'un tableau à |
|---|
| 436 |
<replaceable>N+1</> dimensions. Par exemple : |
|---|
| 437 |
<programlisting> |
|---|
| 438 |
SELECT array_dims(ARRAY[1,2] || ARRAY[[3,4],[5,6]]); |
|---|
| 439 |
array_dims |
|---|
| 440 |
------------ |
|---|
| 441 |
[0:2][1:2] |
|---|
| 442 |
(1 row) |
|---|
| 443 |
</programlisting> |
|---|
| 444 |
</para> |
|---|
| 445 |
|
|---|
| 446 |
<para> |
|---|
| 447 |
Un tableau peut aussi être construit en utilisant les fonctions |
|---|
| 448 |
<function>array_prepend</function>, <function>array_append</function> |
|---|
| 449 |
ou <function>array_cat</function>. Les deux premiers supportent seulement les |
|---|
| 450 |
tableaux à une dimension alors que <function>array_cat</function> supporte les |
|---|
| 451 |
tableaux multidimensionnels. |
|---|
| 452 |
|
|---|
| 453 |
Notez que l'opérateur de concaténation vu ci-dessus est préféré à |
|---|
| 454 |
l'utilisation directe de ces fonctions. En fait, les fonctions sont utilisées |
|---|
| 455 |
principalement pour l'implémentation de l'opérateur de concaténation. |
|---|
| 456 |
Néanmoins, elles pourraient être directement utiles dans la création |
|---|
| 457 |
d'agrégats définis par l'utilisateur. Quelques exemples : |
|---|
| 458 |
|
|---|
| 459 |
<programlisting> |
|---|
| 460 |
SELECT array_prepend(1, ARRAY[2,3]); |
|---|
| 461 |
array_prepend |
|---|
| 462 |
--------------- |
|---|
| 463 |
{1,2,3} |
|---|
| 464 |
(1 row) |
|---|
| 465 |
|
|---|
| 466 |
SELECT array_append(ARRAY[1,2], 3); |
|---|
| 467 |
array_append |
|---|
| 468 |
-------------- |
|---|
| 469 |
{1,2,3} |
|---|
| 470 |
(1 row) |
|---|
| 471 |
|
|---|
| 472 |
SELECT array_cat(ARRAY[1,2], ARRAY[3,4]); |
|---|
| 473 |
array_cat |
|---|
| 474 |
--------------- |
|---|
| 475 |
{1,2,3,4} |
|---|
| 476 |
(1 row) |
|---|
| 477 |
|
|---|
| 478 |
SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]); |
|---|
| 479 |
array_cat |
|---|
| 480 |
--------------------- |
|---|
| 481 |
{{1,2},{3,4},{5,6}} |
|---|
| 482 |
(1 row) |
|---|
| 483 |
|
|---|
| 484 |
SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]); |
|---|
| 485 |
array_cat |
|---|
| 486 |
--------------------- |
|---|
| 487 |
{{5,6},{1,2},{3,4}} |
|---|
| 488 |
</programlisting> |
|---|
| 489 |
</para> |
|---|
| 490 |
</sect2> |
|---|
| 491 |
|
|---|
| 492 |
<sect2> |
|---|
| 493 |
<title>Recherche dans des tableaux</title> |
|---|
| 494 |
|
|---|
| 495 |
<para> |
|---|
| 496 |
Pour rechercher une valeur dans un tableau, vous devez vérifier chaque valeur |
|---|
| 497 |
dans le tableau. Ceci peut se faire à la main si vous connaissez la taille du |
|---|
| 498 |
tableau. Par exemple : |
|---|
| 499 |
|
|---|
| 500 |
<programlisting> |
|---|
| 501 |
SELECT * FROM sal_emp WHERE paye_par_semaine[1] = 10000 OR |
|---|
| 502 |
paye_par_semaine[2] = 10000 OR |
|---|
| 503 |
paye_par_semaine[3] = 10000 OR |
|---|
| 504 |
paye_par_semaine[4] = 10000; |
|---|
| 505 |
</programlisting> |
|---|
| 506 |
|
|---|
| 507 |
Néanmoins, ceci devient rapidement long pour les gros tableaux et n'est pas |
|---|
| 508 |
très utile si la taille du tableau n'est pas certaine. Une autre méthode est |
|---|
| 509 |
décrite dans <xref linkend="functions-comparisons">. La requête ci-dessus |
|---|
| 510 |
est remplaçable par : |
|---|
| 511 |
|
|---|
| 512 |
<programlisting> |
|---|
| 513 |
SELECT * FROM sal_emp WHERE 10000 = ANY (paye_par_semaine); |
|---|
| 514 |
</programlisting> |
|---|
| 515 |
|
|---|
| 516 |
De plus, vous pouvez trouvez les lignes où le tableau n'a que des valeurs |
|---|
| 517 |
égales à 10000 avec : |
|---|
| 518 |
|
|---|
| 519 |
<programlisting> |
|---|
| 520 |
SELECT * FROM sal_emp WHERE 10000 = ALL (paye_par_semaine); |
|---|
| 521 |
</programlisting> |
|---|
| 522 |
|
|---|
| 523 |
</para> |
|---|
| 524 |
|
|---|
| 525 |
<tip> |
|---|
| 526 |
<para> |
|---|
| 527 |
Les tableaux ne sont pas toujours initialisés ; rechercher des éléments |
|---|
| 528 |
spécifiques d'un tableau pourrait être un signe d'une mauvaise conception de |
|---|
| 529 |
la base de données. Utilisez plutôt une table séparée avec une |
|---|
| 530 |
ligne pour chaque élément faisant parti du tableau. Cela sera plus simple |
|---|
| 531 |
pour une recherche et fonctionnera mieux dans le cas d'un grand nombre |
|---|
| 532 |
d'éléments. |
|---|
| 533 |
</para> |
|---|
| 534 |
</tip> |
|---|
| 535 |
</sect2> |
|---|
| 536 |
|
|---|
| 537 |
<sect2> |
|---|
| 538 |
<title>Syntaxe d'entrée et de sortie des tableaux</title> |
|---|
| 539 |
|
|---|
| 540 |
<para> |
|---|
| 541 |
La représentation externe du type texte d'une valeur d'un tableau consiste en |
|---|
| 542 |
des éléments interprétés suivant les règles de conversion d'entrées/sorties |
|---|
| 543 |
pour le type de l'élément du tableau, plus des décorations indiquant la |
|---|
| 544 |
structure du tableau. La décoration consiste en des accolades (<literal>{</> |
|---|
| 545 |
et <literal>}</>) autour des valeurs du tableau et des caractères de |
|---|
| 546 |
délimitation entre éléments adjacents. Le caractère délimiteur est |
|---|
| 547 |
habituellement une virgule (<literal>,</>) mais peut être autre chose : |
|---|
| 548 |
il est déterminé par la configuration <literal>typdelim</> pour le type |
|---|
| 549 |
de l'élément du tableau (parmi les types de données standards supportés par |
|---|
| 550 |
l'implémentation de <productname>PostgreSQL</productname>, le type |
|---|
| 551 |
<literal>box</> utilise un point-virgule (<literal>;</>) mais tous les autres |
|---|
| 552 |
utilisent la virgule). Dans un tableau multidimensionnel, chaque dimension |
|---|
| 553 |
(row, plane, cube, etc.) utilise son propre niveau d'accolades et les |
|---|
| 554 |
délimiteurs doivent être utilisés entre des entités adjacentes au sein d'accolades |
|---|
| 555 |
de même niveau. Vous pouvez insérer un espace blanc avant une accolade gauche, |
|---|
| 556 |
après une accolade droite ou avant toute chaîne d'un élément individuel. |
|---|
| 557 |
Un espace blanc après un élément n'est pas ignoré, néanmoins : après avoir |
|---|
| 558 |
passé l'espace blanc du début, tout - jusqu'à la prochaine accolade droite ou |
|---|
| 559 |
délimiteur - est interprété comme valeur de l'élément. |
|---|
| 560 |
</para> |
|---|
| 561 |
|
|---|
| 562 |
<para> |
|---|
| 563 |
Comme indiqué précédemment, lors de l'écriture de la valeur d'un tableau, |
|---|
| 564 |
vous pouvez écrire des doubles guillemets autour de chaque élément |
|---|
| 565 |
individuel du tableau. Vous <emphasis>devez</> le faire si la valeur de |
|---|
| 566 |
l'élément risque de gêner l'analyseur. Par exemple, les éléments contenant |
|---|
| 567 |
des accolades, des virgules (ou quelque soit le caractère délimiteur), des |
|---|
| 568 |
guillemets doubles, des anti-slash ou des espaces blancs en début doivent |
|---|
| 569 |
être entre guillemets doubles. Pour mettre un guillemet double ou un |
|---|
| 570 |
anti-slash dans la valeur d'un élément d'un tableau entre guillemets, |
|---|
| 571 |
précédez-le avec un anti-slash. Autrement, vous pouvez utiliser le caractère |
|---|
| 572 |
d'échappement anti-slash pour protéger tous les caractères de données qui |
|---|
| 573 |
pourraient être pris pour un élément de syntaxe de tableau ou des espaces blancs |
|---|
| 574 |
à ignorer. |
|---|
| 575 |
</para> |
|---|
| 576 |
|
|---|
| 577 |
<para> |
|---|
| 578 |
La routine de sortie du tableau placera des guillemets doubles autour des |
|---|
| 579 |
valeurs des éléments si elles sont des chaînes vides ou contiennent des |
|---|
| 580 |
accolades, des caractères délimiteurs, des guillemets doubles, des anti-slash |
|---|
| 581 |
ou des espaces blancs. Les guillemets doubles et les anti-slash intégrés |
|---|
| 582 |
aux valeurs des éléments auront un caractère d'échappement, l'anti-slash. |
|---|
| 583 |
Pour les types de données numériques, il est sain de supposer que les doubles |
|---|
| 584 |
guillemets n'apparaîtront jamais, mais pour les types de données texte, |
|---|
| 585 |
vous devez vous préparer à gérer la présence et l'absence de guillemets. |
|---|
| 586 |
(Ceci est un changement du comportement à partir de la version pré-7.2 de |
|---|
| 587 |
<productname>PostgreSQL</productname>.) |
|---|
| 588 |
</para> |
|---|
| 589 |
|
|---|
| 590 |
<note> |
|---|
| 591 |
<para> |
|---|
| 592 |
Rappelez-vous que ce que vous écrivez comme commande SQL sera tout d'abord |
|---|
| 593 |
interprété en tant que chaîne littérale puis en tant que tableau. Ceci |
|---|
| 594 |
double le nombre d'anti-slash dont vous aurez besoin. Par exemple, pour |
|---|
| 595 |
insérer une valeur de tableau de type <type>text</> contenant un anti-slash |
|---|
| 596 |
et un guillemet double, vous aurez besoin d'écrire |
|---|
| 597 |
<programlisting> |
|---|
| 598 |
INSERT ... VALUES ('{"\\\\","\\""}'); |
|---|
| 599 |
</programlisting> |
|---|
| 600 |
Le processeur de la chaîne littérale supprime un niveau d'anti-slash, donc |
|---|
| 601 |
ce qui arrive à l'analyseur de tableau ressemble à <literal>{"\\","\""}</>. |
|---|
| 602 |
A la place, les chaînes remplissant l'entrée du type de données |
|---|
| 603 |
<type>text</> deviennent respectivement <literal>\</> et <literal>"</>. |
|---|
| 604 |
(Si nous travaillions avec un type de données dont la routine d'entrée |
|---|
| 605 |
traitait aussi les anti-slash de manière spéciale, <type>bytea</> par |
|---|
| 606 |
exemple, nous pourrions avoir besoin d'au plus huit anti-slash dans la |
|---|
| 607 |
commande pour en obtenir un dans l'élément stocké.) |
|---|
| 608 |
</para> |
|---|
| 609 |
</note> |
|---|
| 610 |
|
|---|
| 611 |
<tip> |
|---|
| 612 |
<para> |
|---|
| 613 |
La syntaxe du constructeur <literal>ARRAY</> est souvent plus facile à |
|---|
| 614 |
utiliser que la syntaxe du tableau littéral lors de l'écriture de valeurs |
|---|
| 615 |
du tableau en commandes SQL. Avec <literal>ARRAY</>, les valeurs de |
|---|
| 616 |
l'élément individuel sont écrit de la même façon qu'ils auraient été écrit |
|---|
| 617 |
s'ils n'avaient pas fait partie d'un tableau. |
|---|
| 618 |
</para> |
|---|
| 619 |
</tip> |
|---|
| 620 |
</sect2> |
|---|
| 621 |
|
|---|
| 622 |
</sect1> |
|---|