30

这是 Postgresql 9.2.4 上的设置:

CREATE TABLE table (
    id integer NOT NULL,
    some_text text
);

现在我们输入一条记录,其中 为空或空字符串some_text,这样当我们查询时:

SELECT * FROM table WHERE some_text IS NULL;

我把条目拿回来了。到目前为止,一切都很好。

但是,当我查询时:

SELECT * FROM table WHERE some_text NOT ILIKE "%anything%';

我发现什么都没有返回。这是为什么?我希望 null 或空字符串是“不像anything”。

4

2 回答 2

56

在 SQL 中,NULL 不等于任何东西。它也不等于任何东西。

换句话说,如果我不告诉你我的中间名,你也不告诉我你的中间名,我们怎么知道我们的两个中间名是同名还是不同名?我们无法知道。

这经常使人们在 SQL 中绊倒,因为它是“三值逻辑”。表达式可以是 TRUE、FALSE 或 UNKNOWN。我们这些熟悉布尔代数的人都知道,NOT TRUE 是 FALSE,NOT FALSE 是 TRUE。

但棘手的部分是 NOT UNKNOWN 仍然是 UNKNOWN。

因此,您的解决方案要么始终在列中存储非空字符串,要么使用表达式来解释三值逻辑:

SELECT * FROM table WHERE some_text NOT ILIKE "%anything%' OR some_text IS NULL;

或者:

SELECT * FROM table WHERE COALESCE(some_text, '') NOT ILIKE '%anything%';

PostgreSQL 还支持空安全相等运算符

SELECT * FROM table WHERE some_text IS DISTINCT FROM 'anything';

但不幸的是,这仅适用于相等,不适用于带有模式和通配符的 LIKE/ILIKE。

于 2013-08-14T23:05:43.267 回答
9

您可以使用 COALESCE 来实现您的目标,例如

SELECT * FROM table WHERE COALESCE(some_text,'') NOT ILIKE "%anything%';
于 2013-08-14T23:12:16.817 回答