空值和所有列均为空的行类型之间有什么区别吗?Postgres 查询似乎能够区分(显示空列而不是空白),我想知道我是否应该注意什么。例如
CREATE TYPE node AS (
rank integer
, id integer
);
CREATE TABLE hierarchy (
node node
);
INSERT INTO hierarchy (node) VALUES (null);
INSERT INTO hierarchy (node) VALUES ((null, null));
SELECT *, node IS NULL AS check_null FROM hierarchy;
node | check_null ------+------------ | t (,) | t
null 值和所有列均为 null 的行类型之间有什么区别吗?
NULL:node
仍然与(null, null)::node
不同:
SELECT null::node IS DISTINCT FROM (null, null)::node AS dist;
dist ---- t
我同意这令人困惑。手册也可能在这里锐化:
对于非空输入,
IS DISTINCT FROM
与<>
运算符相同。 但是,如果两个输入都为 null,则返回 false,如果只有一个输入 输入为空,则返回 true。
事实证明,面对上面的演示,有点不正确。即使下面有一个提示:
如果
expression
是行值,则当行为真时IS NULL
为 true。 表达式本身为 null 或当行的所有字段均为 null 时。
因此,我们有两种不同的情况,其中行值为空:
- 表达式本身为空。
- 行的所有字段均为空。
应该提到的是,与IS DISTINCT FROM
相比,这两种情况仍然被认为是不同的。可能值得文档错误报告...
有什么我应该注意的吗?
是的。无论DISTINCT
在哪里发挥作用,这两种变体都被认为是不同的:
SELECT DISTINCT * FROM hierarchy;
node1 ------ (,) (2 rows)
请注意第 2 行不可见,因为 psql 以这种方式显示空值。
阻止 (,) 案例发生?
解决您的评论:
CREATE TABLE hierarchy (
node node CHECK (node IS DISTINCT FROM (null, null)::node)
);
请注意两件事:
- 显式强制转换
(null, null)::node
是必需的。 - 仍然允许简单的 NULL 值,只有包含所有 null 值的行违反约束。