一段范围资料的下界没有填写,并不表示这个范围没有内容。PostgreSQL 17的Range Types说明将范围定义为某种元素类型的一段值,并要求该类型具有全序关系,使值位于范围之前、之内或之后能够被清楚判断。[1] 在这个定义下,边界省略与空范围表达的是两种不同状态。

非空范围具有下界与上界,两者之间的点包含在范围内。边界本身是否包含,还需继续判断:包含边界意味着端点也在其中,不包含边界则把端点排除。[1] 文本表示用方括号标包含、圆括号标不包含。因此,两段范围写着同样的端点数值,未必就包含同样的点。

文档的整数例子说明了端点的重要性。[4,4]只包含数值4这一个点,而[4,4)不包含任何点,并被规范成empty。[1] 两者的端点数字完全相同,区别来自右端是否仍被纳入。这里是对官方纸面区间例子的解释,没有执行SQL或据此处理真实数据库记录。

省略边界的结果恰好不是empty。省略下界,表示上界以下的值纳入范围;省略上界,则相应包含下界以上的值。如果两侧都省略,该元素类型的所有值都被考虑在范围内。[1] 一侧没有一个明确端点,不是删掉这一侧的全部元素,而是没有用该侧端点截住范围。

PostgreSQL还明确说,若把缺失边界标为包含,会自动转换为不包含。例如两侧都没有边界值时,包含形式会转为两侧不包含的无界形式。[1] 此处的转换没有把元素集合变成空集。判断范围是否为空,仍需要看它实际包含什么点,而不能只看某处出现圆括号或空白。

无界与元素自身的无穷值,也需要区分。文档将缺失边界视作特殊范围类型值,并说它们位于元素类型自身正负infinity之外。对于支持infinity的timestamp,原文例子中[today,infinity)排除timestamp的infinity值,而[today,infinity]和[today,)包含该值。[1] 右边省略与明确写出一个不包含的infinity端点,在这个类型中并非相同表达。

最后,empty是专门表示没有任何点的空范围。[1] 它与没有下界、没有上界,以及端点值本身为空字符串,都不能只用日常的“空”字合并。对数据库文档读者,先分清元素类型,再辨边界是否存在及是否包含,才能准确理解一段范围的成员关系。

本文固定采用PostgreSQL 17第8.17节定义及8.17.3至8.17.5连续说明,没有执行查询、创建类型或索引,也不推断生产数据。页首其他版本新闻不作为本节首发依据;这些例子说明的是范围语义,而不是数据库性能或业务金额判断。

资料:[1] https://www.postgresql.org/docs/17/rangetypes.html

信息来源

本文基于上述公开资料整理,未使用来源页面的图片、视频或嵌入媒体。