non-slice case, it's best to use slice syntax
for all dimensions, e.g., <literal>[1:2][1:1]</literal>, not <literal>[2][1:1]</literal>.
</para>
<para>
It is possible to omit the <replaceable>lower-bound</replaceable> and/or
<replaceable>upper-bound</replaceable> of a slice specifier; the missing
bound is replaced by the lower or upper limit of the array's subscripts.
For example:
<programlisting>
SELECT schedule[:2][2:] FROM sal_emp WHERE name = 'Bill';
schedule
------------------------
{{lunch},{presentation}}
(1 row)
SELECT schedule[:][1:1] FROM sal_emp WHERE name = 'Bill';
schedule
------------------------
{{meeting},{training}}
(1 row)
</programlisting>
</para>
<para>
An array subscript expression will return null if either the array itself or
any of the subscript expressions are null. Also, null is returned if a
subscript is outside the array bounds (this case does not raise an error).
For example, if <literal>schedule</literal>
currently has the dimensions <literal>[1:3][1:2]</literal> then referencing
<literal>schedule[3][3]</literal> yields NULL. Similarly, an array reference
with the wrong number of subscripts yields a null rather than an error.
</para>
<para>
An array slice expression likewise yields null if the array itself or
any of the subscript expressions are null. However, in other
cases such as selecting an array slice that
is completely outside the current array bounds, a slice expression
yields an empty (zero-dimensional) array instead of null. (This
does not match non-slice behavior and is done for historical reasons.)
If the requested slice partially overlaps the array bounds, then it
is silently reduced to just the overlapping region instead of
returning null.
</para>
<para>
The current dimensions of any array value can be retrieved with the
<function>array_dims</function> function:
<programlisting>
SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol';
array_dims
------------
[1:2][1:2]
(1 row)
</programlisting>
<function>array_dims</function> produces a <type>text</type> result,
which is convenient for people to read but perhaps inconvenient
for programs. Dimensions can also be retrieved with
<function>array_upper</function> and <function>array_lower</function>,
which return the upper and lower bound of a
specified array dimension, respectively:
<programlisting>
SELECT array_upper(schedule, 1) FROM sal_emp WHERE name = 'Carol';
array_upper
-------------
2
(1 row)
</programlisting>
<function>array_length</function> will return the length of a specified
array dimension:
<programlisting>
SELECT array_length(schedule, 1) FROM sal_emp WHERE name = 'Carol';
array_length
--------------
2
(1 row)
</programlisting>
<function>cardinality</function> returns the total number of elements in an
array across all dimensions. It is effectively the number of rows a call to
<function>unnest</function> would yield:
<programlisting>
SELECT cardinality(schedule) FROM sal_emp WHERE name = 'Carol';
cardinality
-------------
4
(1 row)
</programlisting>
</para>
</sect2>
<sect2 id="arrays-modifying">
<title>Modifying Arrays</title>
<indexterm>
<primary>array</primary>
<secondary>modifying</secondary>
</indexterm>
<para>
An array value can be replaced completely:
<programlisting>
UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
WHERE name = 'Carol';
</programlisting>
or using the <literal>ARRAY</literal> expression syntax:
<programlisting>
UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000]
WHERE name = 'Carol';
</programlisting>
An array can also be updated at a single element:
<programlisting>
UPDATE sal_emp SET pay_by_quarter[4] = 15000
WHERE name = 'Bill';
</programlisting>
or updated in a slice:
<programlisting>
UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
WHERE name = 'Carol';