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>
2312CREATE TABLE sal_emp (
2413 name text,
25- pay_by_quarterint4 [],
14+ pay_by_quarterinteger [],
2615 schedule text[][]
2716);
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.
4133
42- <ProgramListing >
34+ <programlisting >
4335INSERT INTO sal_emp
4436 VALUES ('Bill',
4537 '{10000, 10000, 10000, 10000}',
@@ -49,143 +41,196 @@ INSERT INTO sal_emp
4941 VALUES ('Carol',
5042 '{20000, 25000, 25000, 25000}',
5143 '{{"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:
5852
59- <ProgramListing >
53+ <programlisting >
6054SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
6155
6256 name
6357-------
6458 Carol
6559(1 row)
66- </ProgramListing >
60+ </programlisting >
6761
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>
7267
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:
7670
77- <ProgramListing >
71+ <programlisting >
7872SELECT pay_by_quarter[3] FROM sal_emp;
7973
8074 pay_by_quarter
8175----------------
8276 10000
8377 25000
8478(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 itemon Bill's
88+ schedule for the first two days of the week:
9589
96- <ProgramListing >
90+ <programlisting >
9791SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
9892
9993 schedule
10094--------------------
10195 {{"meeting"},{""}}
10296(1 row)
103- </ProgramListing >
97+ </programlisting >
10498
105- We could also have written
99+ We could also have written
106100
107- <ProgramListing >
101+ <programlisting >
108102SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill';
109- </ProgramListing >
103+ </programlisting >
110104
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 >
117111
118- <Para >
119- An array value can be replaced completely:
112+ <para >
113+ An array value can be replaced completely:
120114
121- <ProgramListing >
115+ <programlisting >
122116UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
123117 WHERE name = 'Carol';
124- </ProgramListing >
118+ </programlisting >
125119
126- or updated at a single element:
120+ or updated at a single element:
127121
128- <ProgramListing >
122+ <programlisting >
129123UPDATE sal_emp SET pay_by_quarter[4] = 15000
130124 WHERE name = 'Bill';
131- </ProgramListing >
125+ </programListing >
132126
133- or updated in a slice:
127+ or updated in a slice:
134128
135- <ProgramListing >
129+ <programlisting >
136130UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
137131 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 >
156150CREATE TABLE tictactoe (
157- squaresint4 [3][3]
151+ squaresinteger [3][3]
158152);
159- </ProgramListing >
153+ </programlisting >
160154
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 >
165159
166- <Para >
167- Actually, the current implementationdoesn'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 implementationdoes 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 >
172166
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:
176170
177- <ProgramListing >
171+ <programlisting >
178172SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol';
179173
180174 array_dims
181175------------
182176 [1:2][1:1]
183177(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>