1
- <!--
2
- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.9 2001/01/13 23:58:55 petere Exp $
3
- -->
4
-
5
- <Chapter Id="arrays">
6
- <Title>Arrays</Title>
7
-
8
- <Para>
9
- <Note>
10
- <Para>
11
- This must become a chapter on array behavior. Volunteers? - thomas 1998-01-12
12
- </Para>
13
- </Note>
14
- </Para>
15
-
16
- <Para>
17
- <ProductName>Postgres</ProductName> allows columns of a table
18
- to be defined as variable-length multi-dimensional
19
- arrays. Arrays of any built-in type or user-defined type
20
- can be created. To illustrate their use, we create this table:
21
-
22
- <ProgramListing>
1
+ <!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.10 2001/01/26 23:40:39 petere Exp $ -->
2
+
3
+ <chapter id="arrays">
4
+ <title>Arrays</title>
5
+
6
+ <para>
7
+ <productname>Postgres</productname> allows columns of a table to be
8
+ defined as variable-length multi-dimensional arrays. Arrays of any
9
+ built-in type or user-defined type can be created. To illustrate
10
+ their use, we create this table:
11
+ <programlisting>
23
12
CREATE TABLE sal_emp (
24
13
name text,
25
- pay_by_quarter int4 [],
14
+ pay_by_quarter integer [],
26
15
schedule text[][]
27
16
);
28
- </ProgramListing>
29
- </Para>
30
-
31
- <Para>
32
- The above query will create a table named <FirstTerm>sal_emp</FirstTerm> with
33
- a <FirstTerm>text</FirstTerm> string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm>
34
- (pay_by_quarter), which represents the employee's
35
- salary by quarter, and a two-dimensional array of <FirstTerm>text</FirstTerm>
36
- (schedule), which represents the employee's weekly
37
- schedule. Now we do some <FirstTerm>INSERT</FirstTerm>s; note that when
38
- appending to an array, we enclose the values within
39
- braces and separate them by commas. If you know <FirstTerm>C</FirstTerm>,
40
- this is not unlike the syntax for initializing structures.
17
+ </programlisting>
18
+ The above query will create a table named
19
+ <structname>sal_emp</structname> with a <type>text</type> string
20
+ (<structfield>name</structfield>), a one-dimensional array of type
21
+ <type>integer</type> (<structfield>pay_by_quarter</structfield>),
22
+ which shall represent the employee's salary by quarter, and a
23
+ two-dimensional array of <type>text</type>
24
+ (<structfield>schedule</structfield>), which represents the
25
+ employee's weekly schedule.
26
+ </para>
27
+
28
+ <para>
29
+ Now we do some <command>INSERT</command>s; note that when appending
30
+ to an array, we enclose the values within braces and separate them
31
+ by commas. If you know C, this is not unlike the syntax for
32
+ initializing structures.
41
33
42
- <ProgramListing >
34
+ <programlisting >
43
35
INSERT INTO sal_emp
44
36
VALUES ('Bill',
45
37
'{10000, 10000, 10000, 10000}',
@@ -49,143 +41,196 @@ INSERT INTO sal_emp
49
41
VALUES ('Carol',
50
42
'{20000, 25000, 25000, 25000}',
51
43
'{{"talk", "consult"}, {"meeting"}}');
52
- </ProgramListing>
53
-
54
- Now, we can run some queries on sal_emp. First, we
55
- show how to access a single element of an array at a
56
- time. This query retrieves the names of the employees
57
- whose pay changed in the second quarter:
44
+ </programlisting>
45
+ </para>
46
+
47
+ <para>
48
+ Now, we can run some queries on <structname>sal_emp</structname>.
49
+ First, we show how to access a single element of an array at a time.
50
+ This query retrieves the names of the employees whose pay changed in
51
+ the second quarter:
58
52
59
- <ProgramListing >
53
+ <programlisting >
60
54
SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
61
55
62
56
name
63
57
-------
64
58
Carol
65
59
(1 row)
66
- </ProgramListing >
60
+ </programlisting >
67
61
68
- <ProductName>Postgres</ProductName> uses the "one-based" numbering
69
- convention for arrays --- that is, an array of n elements starts with
70
- array[1] and ends with array[n].
71
- </Para>
62
+ <productname>Postgres</productname> uses the
63
+ <quote>one-based</quote> numbering convention for arrays, that is,
64
+ an array of n elements starts with <literal>array[1]</literal> and
65
+ ends with <literal>array[n]</literal>.
66
+ </para>
72
67
73
- <Para>
74
- This query retrieves the third quarter pay of all
75
- employees:
68
+ <para>
69
+ This query retrieves the third quarter pay of all employees:
76
70
77
- <ProgramListing >
71
+ <programlisting >
78
72
SELECT pay_by_quarter[3] FROM sal_emp;
79
73
80
74
pay_by_quarter
81
75
----------------
82
76
10000
83
77
25000
84
78
(2 rows)
85
- </ProgramListing >
86
- </Para >
87
-
88
- <Para >
89
- We can also access arbitrary rectangular slices of an array, or
90
- subarrays. An array slice is denoted by writing
91
- < replaceable>lower subscript</replaceable> <literal>:</literal>
92
- <replaceable>upper subscript</replaceable> for one or more array
93
- dimensions. This query retrieves the first item on
94
- Bill's schedule for the first two days of the week:
79
+ </programlisting >
80
+ </para >
81
+
82
+ <para >
83
+ We can also access arbitrary rectangular slices of an array, or
84
+ subarrays. An array slice is denoted by writing
85
+ <literal>< replaceable>lower subscript</replaceable> :
86
+ <replaceable>upper subscript</replaceable></literal> for one or more
87
+ array dimensions. This query retrieves the first item on Bill's
88
+ schedule for the first two days of the week:
95
89
96
- <ProgramListing >
90
+ <programlisting >
97
91
SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
98
92
99
93
schedule
100
94
--------------------
101
95
{{"meeting"},{""}}
102
96
(1 row)
103
- </ProgramListing >
97
+ </programlisting >
104
98
105
- We could also have written
99
+ We could also have written
106
100
107
- <ProgramListing >
101
+ <programlisting >
108
102
SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill';
109
- </ProgramListing >
103
+ </programlisting >
110
104
111
- with the same result. An array subscripting operation is taken to
112
- represent an array slice if any of the subscripts are written in
113
- the form <replaceable>lower</replaceable> <literal>:</literal>
114
- <replaceable>upper</replaceable>. A lower bound of 1 is assumed
115
- for any subscript where only one value is specified.
116
- </Para >
105
+ with the same result. An array subscripting operation is taken to
106
+ represent an array slice if any of the subscripts are written in the
107
+ form <replaceable>lower</replaceable> <literal>:</literal>
108
+ <replaceable>upper</replaceable>. A lower bound of 1 is assumed for
109
+ any subscript where only one value is specified.
110
+ </para >
117
111
118
- <Para >
119
- An array value can be replaced completely:
112
+ <para >
113
+ An array value can be replaced completely:
120
114
121
- <ProgramListing >
115
+ <programlisting >
122
116
UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
123
117
WHERE name = 'Carol';
124
- </ProgramListing >
118
+ </programlisting >
125
119
126
- or updated at a single element:
120
+ or updated at a single element:
127
121
128
- <ProgramListing >
122
+ <programlisting >
129
123
UPDATE sal_emp SET pay_by_quarter[4] = 15000
130
124
WHERE name = 'Bill';
131
- </ProgramListing >
125
+ </programListing >
132
126
133
- or updated in a slice:
127
+ or updated in a slice:
134
128
135
- <ProgramListing >
129
+ <programlisting >
136
130
UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
137
131
WHERE name = 'Carol';
138
- </ProgramListing >
139
- </Para >
140
-
141
- <Para >
142
- An array can be enlarged by assigning to an element adjacent to
143
- those already present, or by assigning to a slice that is adjacent
144
- to or overlaps the data already present.
145
- For example, if an array value currently has 4 elements, it will
146
- have five elements after an update that assigns to array[5].
147
- Currently, enlargement in this fashion is only
148
- allowed for one-dimensional arrays, not multidimensional arrays.
149
- </Para >
150
-
151
- <Para >
152
- The syntax for CREATE TABLE allows fixed-length arrays to be
153
- defined:
154
-
155
- <ProgramListing >
132
+ </programlisting >
133
+ </para >
134
+
135
+ <para >
136
+ An array can be enlarged by assigning to an element adjacent to
137
+ those already present, or by assigning to a slice that is adjacent
138
+ to or overlaps the data already present. For example, if an array
139
+ value currently has 4 elements, it will have five elements after an
140
+ update that assigns to array[5]. Currently, enlargement in this
141
+ fashion is only allowed for one-dimensional arrays, not
142
+ multidimensional arrays.
143
+ </para >
144
+
145
+ <para >
146
+ The syntax for <command> CREATE TABLE</command> allows fixed-length
147
+ arrays to be defined:
148
+
149
+ <programlisting >
156
150
CREATE TABLE tictactoe (
157
- squares int4 [3][3]
151
+ squares integer [3][3]
158
152
);
159
- </ProgramListing >
153
+ </programlisting >
160
154
161
- However, the current implementation does not enforce the array
162
- size limits --- the behavior is the same as for arrays of
163
- unspecified length.
164
- </Para >
155
+ However, the current implementation does not enforce the array size
156
+ limits --- the behavior is the same as for arrays of unspecified
157
+ length.
158
+ </para >
165
159
166
- <Para >
167
- Actually, the current implementation doesn't enforce the declared
168
- number of dimensions either. Arrays of a particular base type
169
- are all considered to be of the same type, regardless of size or
170
- number of dimensions.
171
- </Para >
160
+ <para >
161
+ Actually, the current implementation does not enforce the declared
162
+ number of dimensions either. Arrays of a particular base type are
163
+ all considered to be of the same type, regardless of size or number
164
+ of dimensions.
165
+ </para >
172
166
173
- <Para >
174
- The current dimensions of any array value can be retrieved with
175
- the <function>array_dims</function> function:
167
+ <para >
168
+ The current dimensions of any array value can be retrieved with the
169
+ <function>array_dims</function> function:
176
170
177
- <ProgramListing >
171
+ <programlisting >
178
172
SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol';
179
173
180
174
array_dims
181
175
------------
182
176
[1:2][1:1]
183
177
(1 row)
184
- </ProgramListing>
185
-
186
- <function>array_dims</function> produces a <type>text</type> result,
187
- which is convenient for people to read but perhaps not so convenient
188
- for programs.
189
- </Para>
190
-
191
- </Chapter>
178
+ </programlisting>
179
+
180
+ <function>array_dims</function> produces a <type>text</type> result,
181
+ which is convenient for people to read but perhaps not so convenient
182
+ for programs.
183
+ </para>
184
+
185
+ <para>
186
+ To search for a value in an array, you must check each value of the
187
+ array. This can be done by hand (if you know the size of the array):
188
+
189
+ <programlisting>
190
+ SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
191
+ pay_by_quarter[2] = 10000 OR
192
+ pay_by_quarter[3] = 10000 OR
193
+ pay_by_quarter[4] = 10000;
194
+ </programlisting>
195
+
196
+ However, this quickly becomes tedious for large arrays, and is not
197
+ helpful if the size of the array is unknown. Although it is not part
198
+ of the primary <productname>PostgreSQL</productname> distribution,
199
+ in the contributions directory, there is an extension to
200
+ <productname>PostgreSQL</productname> that defines new functions and
201
+ operators for iterating over array values. Using this, the above
202
+ query could be:
203
+
204
+ <programlisting>
205
+ SELECT * FROM sal_emp WHERE pay_by_quarter[1:4] *= 10000;
206
+ </programlisting>
207
+
208
+ To search the entire array (not just specified columns), you could
209
+ use:
210
+
211
+ <programlisting>
212
+ SELECT * FROM sal_emp WHERE pay_by_quarter *= 10000;
213
+ </programlisting>
214
+
215
+ In addition, you could find rows where the array had all values
216
+ equal to 10 000 with:
217
+
218
+ <programlisting>
219
+ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
220
+ </programlisting>
221
+
222
+ To install this optional module, look in the
223
+ <filename>contrib/array</filename> directory of the
224
+ <productname>PostgreSQL</productname> source distribution.
225
+ </para>
226
+
227
+ <tip>
228
+ <para>
229
+ Arrays are not lists; using arrays in the manner described in the
230
+ previous paragraph is often a sign of database misdesign. The
231
+ array field should generally be split off into a separate table.
232
+ Tables can obviously be searched easily.
233
+ </para>
234
+ </tip>
235
+
236
+ </chapter>
0 commit comments