<literal><<</literal>,
<literal>>></literal>,
<literal>-|-</literal>,
<literal>&<</literal>, and
<literal>&></literal>.
See <xref linkend="range-operators-table"/> for more information.
</para>
<para>
In addition, B-tree and hash indexes can be created for table columns of
range types. For these index types, basically the only useful range
operation is equality. There is a B-tree sort ordering defined for range
values, with corresponding <literal><</literal> and <literal>></literal> operators,
but the ordering is rather arbitrary and not usually useful in the real
world. Range types' B-tree and hash support is primarily meant to
allow sorting and hashing internally in queries, rather than creation of
actual indexes.
</para>
</sect2>
<sect2 id="rangetypes-constraint">
<title>Constraints on Ranges</title>
<indexterm>
<primary>range type</primary>
<secondary>exclude</secondary>
</indexterm>
<para>
While <literal>UNIQUE</literal> is a natural constraint for scalar
values, it is usually unsuitable for range types. Instead, an
exclusion constraint is often more appropriate
(see <link linkend="sql-createtable-exclude">CREATE TABLE
... CONSTRAINT ... EXCLUDE</link>). Exclusion constraints allow the
specification of constraints such as <quote>non-overlapping</quote> on a
range type. For example:
<programlisting>
CREATE TABLE reservation (
during tsrange,
EXCLUDE USING GIST (during WITH &&)
);
</programlisting>
That constraint will prevent any overlapping values from existing
in the table at the same time:
<programlisting>
INSERT INTO reservation VALUES
('[2010-01-01 11:30, 2010-01-01 15:00)');
INSERT 0 1
INSERT INTO reservation VALUES
('[2010-01-01 14:45, 2010-01-01 15:45)');
ERROR: conflicting key value violates exclusion constraint "reservation_during_excl"
DETAIL: Key (during)=(["2010-01-01 14:45:00","2010-01-01 15:45:00")) conflicts
with existing key (during)=(["2010-01-01 11:30:00","2010-01-01 15:00:00")).
</programlisting>
</para>
<para>
You can use the <link linkend="btree-gist"><literal>btree_gist</literal></link>
extension to define exclusion constraints on plain scalar data types, which
can then be combined with range exclusions for maximum flexibility. For
example, after <literal>btree_gist</literal> is installed, the following
constraint will reject overlapping ranges only if the meeting room numbers
are equal:
<programlisting>
CREATE EXTENSION btree_gist;
CREATE TABLE room_reservation (
room text,
during tsrange,
EXCLUDE USING GIST (room WITH =, during WITH &&)
);
INSERT INTO room_reservation VALUES
('123A', '[2010-01-01 14:00, 2010-01-01 15:00)');
INSERT 0 1
INSERT INTO room_reservation VALUES
('123A', '[2010-01-01 14:30, 2010-01-01 15:30)');
ERROR: conflicting key value violates exclusion constraint "room_reservation_room_during_excl"
DETAIL: Key (room, during)=(123A, ["2010-01-01 14:30:00","2010-01-01 15:30:00")) conflicts
with existing key (room, during)=(123A, ["2010-01-01 14:00:00","2010-01-01 15:00:00")).
INSERT INTO room_reservation VALUES
('123B', '[2010-01-01 14:30, 2010-01-01 15:30)');
INSERT 0 1
</programlisting>
</para>
</sect2>
</sect1>