小编Nic*_*ise的帖子

为什么 PostgreSQL 认为范围类型中的 NULL 边界与无限边界不同?

作为序言,我不是问NULL 边界和无限边界之间有什么区别 - 这在另一个问题中有所介绍。相反,我问为什么PostgreSQL 会区分 NULL 和无限边界(据我所知)它们的功能完全相同。

我最近开始使用 PostgreSQL 的范围类型,我对范围类型中 NULL 值的含义有点困惑。文档说:

范围的下限可以省略,这意味着所有小于上限的值都包含在范围 中,例如(,3]。同样,如果省略范围的上限,则所有大于下限的值都包含在范围中。如果下限和上限都被省略,则元素类型的所有值都被认为在该范围内。

这对我来说表明范围中省略的边界(与范围类型的构造函数中指定的等效 NULL 边界)应被视为无限。然而,PostgreSQL 区分了 NULL 边界和无限边界。文档继续:

您可以将[范围内]的这些缺失值视为+/-无穷大,但它们是特殊范围类型值,并且被视为超出任何范围元素类型的+/-无穷大值。

这令人费解。“超越无穷大”没有意义,因为无限值的全部要点是没有什么可以大于+无穷大或小于-无穷大。这并没有破坏“范围内的元素”类型的检查,但它确实引入了一个有趣的主键案例,我认为大多数人都不会想到。或者至少,没想到。

假设我们创建一个基本表,其唯一字段是日期范围,这也是 PK:

CREATE TABLE public.range_test
(
    id daterange NOT NULL,
    PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)

然后我们可以毫无问题地用以下数据填充它:

INSERT INTO range_test VALUES (daterange('-infinity','2021-05-21','[]'));
INSERT INTO range_test VALUES (daterange(NULL,'2021-05-21','[]'));
Run Code Online (Sandbox Code Playgroud)

选择所有数据表明我们有这两个元组:

[-infinity,2021-05-22)
(,2021-05-22)
Run Code Online (Sandbox Code Playgroud)

因此这两个元组是不同的,否则就会出现主键违规。但同样,当我们处理构成范围的实际元素时,NULL 边界和无限边界的工作原理完全相同。例如,不存在date值 X 使得 的结果X <@ …

postgresql null range infinity

6
推荐指数
1
解决办法
1210
查看次数

标签 统计

infinity ×1

null ×1

postgresql ×1

range ×1