为什么x IS NOT NULL不等于NOT x IS NULL?
这段代码:
CREATE TABLE bug_test (
id int,
name text
);
INSERT INTO bug_test
VALUES (1, NULL);
DO $$
DECLARE
v_bug_test bug_test;
BEGIN
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);
SELECT *
INTO v_bug_test
FROM bug_test
WHERE id = 1;
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NULL);
RAISE NOTICE '%: %', v_bug_test, (v_bug_test IS NOT NULL);
RAISE NOTICE '%: %', v_bug_test, (NOT v_bug_test IS NULL);
END
$$;
DROP TABLE bug_test;
Run Code Online (Sandbox Code Playgroud)
给出以下输出:
(,): t
(,): f
(,): f
(1,): f
(1,): f ???
(1,): t
Run Code Online (Sandbox Code Playgroud)
虽然我希望得到这个输出:
(,): t
(,): f
(,): f
(1,): f
(1,): t <<<
(1,): t
Run Code Online (Sandbox Code Playgroud)
joa*_*olo 18
您必须区分两种情况:将一个 COLUMN 与 NULL 进行比较,或者将整个 ROW (RECORD) 与 NULL 进行比较。
考虑以下查询:
SELECT
id,
txt,
txt IS NULL AS txt_is_null,
NOT txt IS NULL AS not_txt_is_null,
txt IS NOT NULL AS txt_is_not_null
FROM
(VALUES
(1::integer, NULL::text)
)
AS x(id, txt) ;
Run Code Online (Sandbox Code Playgroud)
你得到这个:
+----+-----+-------------+-----------------+-----------------+
| id | txt | txt_is_null | not_txt_is_null | txt_is_not_null |
+----+-----+-------------+-----------------+-----------------+
| 1 | | t | f | f |
+----+-----+-------------+-----------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
我想,这就是你和我所期望的。您正在根据 NULL 检查一个 COLUMN,并且您得到“txt IS NOT NULL”和“NOT txt IS NULL”是等效的。
但是,如果您进行不同的检查:
SELECT
id,
txt,
x IS NULL AS x_is_null,
NOT x IS NULL AS not_x_is_null,
x IS NOT NULL AS x_is_not_null
FROM
(VALUES
(1, NULL)
)
AS x(id, txt) ;
Run Code Online (Sandbox Code Playgroud)
然后你得到
+----+-----+-----------+---------------+---------------+
| id | txt | x_is_null | not_x_is_null | x_is_not_null |
+----+-----+-----------+---------------+---------------+
| 1 | | f | t | f |
+----+-----+-----------+---------------+---------------+
Run Code Online (Sandbox Code Playgroud)
这可能令人惊讶。一件事看起来合理 (x IS NULL) 和 (NOT x IS NULL) 是相反的。另一件事(“x IS NULL”和“x IS NOT NULL”都不为真),看起来很奇怪。
但是,这是PostgreSQL 文档所说的应该发生的情况:
如果表达式是行值,那么当行表达式本身为空或所有行的字段为空时,IS NULL 为真,而当行表达式本身为非空且所有行的字段都为空时,IS NOT NULL 为真非空。由于这种行为,IS NULL 和 IS NOT NULL 并不总是为行值表达式返回相反的结果;特别是,同时包含空字段和非空字段的行值表达式将为两个测试返回 false。在某些情况下,最好编写 row IS DISTINCT FROM NULL 或 row IS NOT DISTINCT FROM NULL,这将简单地检查整个行值是否为空,而无需对行字段进行任何额外测试。
我必须承认,我认为我从未使用过针对 null 的行值比较,但我想如果存在这种可能性,那么可能会有一些用例。无论如何,我认为这并不常见。
| 归档时间: |
|
| 查看次数: |
3269 次 |
| 最近记录: |