9 空值(NULL)
NULL 是 SQL 中表示未知或缺失的标记。它不是零,不是空字符串,也不等于任何值,甚至不等于另一个 NULL。这种三值逻辑(真、假、未知)引发的 SQL 错误比其他任何特性都多,不过一旦熟悉,规则其实很简单。
本章要点
NULL表示什么- 用
IS NULL/IS NOT NULL检查NULL NULL如何在表达式和比较中传播NULL在AND/OR中的行为(三值逻辑)- 用
COALESCE和NULLIF替换NULL(译注:此处原文概括不够准确;前者用非空值替换空值,后者可将指定值转为空值。)
示例
= NULL 不起作用,是因为比较结果是 NULL,不是 TRUE,所以 WHERE 会排除这一行。<>、<、>、IN、BETWEEN 等也是如此;几乎所有操作符都会在任一操作数为 NULL 时返回 NULL。例外是 IS NULL、IS NOT NULL、IS DISTINCT FROM 和 IS NOT DISTINCT FROM(后两者分别是能正确处理 NULL 的 <> 和 =)。
COALESCE(a, b, c) 返回第一个不是 NULL 的参数。这是提供默认值的标准做法,例如 COALESCE(nickname, first_name, 'Anonymous')。NULLIF(a, b) 在 a = b 时返回 NULL;如果想把用作标记的特殊值转回 NULL,它就很方便(例如 NULLIF(comment, ''))。
三值逻辑表很短,值得记住:TRUE OR NULL 是 TRUE(至少有一侧为真),但 TRUE AND NULL 是 NULL(不知道另一侧的值)。FALSE AND NULL 是 FALSE(有一侧为假就够了)。FALSE OR NULL 是 NULL。
运行示例
运行方式:
常见陷阱
- 忘记聚合会跳过 NULL:
SUM、AVG、MIN、MAX、COUNT(col)都忽略 NULL 输入。COUNT(*)则统计每一行,包括含有 NULL 的行。 - 只要子查询返回一个 NULL,
NOT IN (subquery)就会得到空结果,因为x <> NULL的结果是NULL。优先使用NOT EXISTS。 NULL <> NULL是未知(NULL),不是真。DISTINCT把 NULL 归为一组;IS DISTINCT FROM提供的比较则总是返回真或假。- 默认排序:
ORDER BY col ASC把 NULL 排在最后,DESC把它们排在最前。明确指定NULLS FIRST/NULLS LAST,让结果符合预期。
如果确实需要能正确处理 NULL 的相等比较,请用 IS NOT DISTINCT FROM。例如,WHERE a IS NOT DISTINCT FROM b 在两者相等或两者都为 NULL 时为真。
依次运行 SELECT 1 = NULL;、SELECT 1 IS NOT NULL;、SELECT NULL IS NOT DISTINCT FROM NULL;,看看结果有何不同。然后尝试 SELECT count(*) AS rows, count(b) AS non_null_b FROM (VALUES (1, NULL), (2, 'x')) AS t(a, b);。
下载
SQL 文件: nulls.sql · 全部示例文件 · 准备工作