范围类型是表达某种元素类型的一个值的范围的数据类型。范围类型可以表达一种单一范围值中的多个元素值,并且可以很清晰地表达诸如范围重叠等概念。本文将对范围类型进行简单介绍。
PostgreSQL带有以下几种内建范围类型:
1) int4range (integer范围)
2) int8range (bigint范围)
3) numrange (numeric范围)
4) tsrange (不带时区的timestamp范围)
5) tstzrange (带时区的timestamp范围)
6) daterange (date范围)
此外,可以使用自定义的范围类型。
有边界的范围
每一个非空范围都有两个界限,下界和上界。这些值之间的所有点都被包括在范围内。一个包含界限意味着边界点本身也被包括在范围内,而一个排除边界意味着边界点不被包括在范围内。
在一个范围的文本形式中,一个包含下界被表达为“[”而一个排除下界被表达为“(”。同样,一个包含上界被表达为“]”而一个排除上界被表达为“)”。
函数lower_inc和upper_inc分别测试一个范围值的上下界。
一个范围值的输入必须遵循下列模式之一:
(lower-bound,upper-bound)
(lower-bound,upper-bound]
[lower-bound,upper-bound)
[lower-bound,upper-bound]
empty
无边界的范围
一个范围的下界可以被忽略,这意味着所有小于上界的点都被包括在范围中。同样,如果范围的上界被忽略,那么所有比上界大的的都被包括在范围中。如果上下界都被忽略,该元素类型的所有值都被认为在该范围中。
函数lower_inf和upper_inf分别测试一个范围的无限上下界。
构建范围
每一种范围类型都有一个与其同名的构造器函数。构造器函数接受两个或三个参数。两个参数的形式以标准的形式构造一个范围(下界是包含的,上界是排除的),而三个参数的形式按照第三个参数指定的界限形式构造一个范围。第三个参数必须是下列字符串之一:“()”、 “(]”、 “[)”或者 “[]”。
举几个例子来说明构建范围的方法:
1) 完整的形式:包括下界、上界以及指示界限包含性/排除性的文本参数。
postgres=# select tsrange('2018-10-31 12:00:00','2018-11-11 00:00:00','[]');
tsrange
-----------------------------------------------
["2018-10-31 12:00:00","2018-11-11 00:00:00"]
(1 row)
2) 如果第三个参数被忽略,则默认为“[)”。
postgres=# select numrange(2.5,12.0);
numrange
------------
[2.5,12.0)
(1 row)
3) 为一个界限使用null导致范围在该边界是无界的。
postgres=# select numrange(null,3.0);
numrange
----------
(,3.0)
(1 row)
范围索引
可以为范围类型的表列创建GiST和SP-GiST索引。一个GiST或SP-GiST索引可以加速涉及以下范围操作符的查询:
=
&&
<@
@>
<<
>>
-|-
&<
&>
此外,B-树和哈希索引可以在范围类型的表列上创建。
范围上的约束
唯一约束通常不适合于范围类型。作为替代,排除约束是更加适合的方式。例如:
postgres=# create table orders(order_time tsrange,exclude using gist(order_time with &&));
CREATE TABLE
该约束将阻止任何重叠值同时存在于表中,例如:
postgres=# insert into orders values('[2018-10-31 12:00,2018-10-31 17:00)');
INSERT 0 1
postgres=# insert into orders values('[2018-10-31 15:00,2018-10-31 18:00)');
2018-10-31 17:21:37.280 CST [2119] ERROR: conflicting key value violates exclusion constraint "orders_order_time_excl"
2018-10-31 17:21:37.280 CST [2119] DETAIL: Key (order_time)=(["2018-10-31 15:00:00","2018-10-31 18:00:00")) conflicts with existing key (order_time)=(["2018-10-31 12:00:00","2018-10-31 17:00:00")).
2018-10-31 17:21:37.280 CST [2119] STATEMENT: insert into orders values('[2018-10-31 15:00,2018-10-31 18:00)');
ERROR: conflicting key value violates exclusion constraint "orders_order_time_excl"
DETAIL: Key (order_time)=(["2018-10-31 15:00:00","2018-10-31 18:00:00")) conflicts with existing key (order_time)=(["2018-10-31 12:00:00","2018-10-31 17:00:00")).
By Kalath