讲解
NULL 表示「未知」或「不适用」,它不是空字符串、不是 0,而是一个特殊标记。学生表里陈静的城市是 NULL,表示「没填」,和填了空字符串是两回事。理解 NULL 的关键是「三值逻辑」:任何与 NULL 的比较结果都是 NULL(既不真也不假),在 WHERE 里效果等同于不通过。这就是为什么 WHERE age = NULL 永远查不到行。
判断 NULL 必须用专门的运算符:IS NULL 和 IS NOT NULL。WHERE city IS NULL 查出城市未知的学生;WHERE city IS NOT NULL 则相反。逻辑运算里 NULL 也遵循三值规则:TRUE AND NULL 得 NULL,TRUE OR NULL 得 TRUE,NOT NULL 还是 NULL——记不全没关系,记住「涉 NULL 的比较要显式处理」即可。
处理 NULL 最常用的函数是 COALESCE:返回参数里第一个非 NULL 的值,COALESCE(city, '未知') 把 NULL 城市显示成「未知」。SQLite 还有等价的双参数简写 IFNULL(city, '未知'),但 COALESCE 是标准 SQL,可移植性更好。聚合时也要注意:COUNT(*) 数所有行,COUNT(city) 只数城市非 NULL 的行;AVG、SUM 同样跳过 NULL。
示例
城市未知与城市已知的学生分别是谁:
SELECT name, city FROM students WHERE city IS NULL;
SELECT name, city FROM students WHERE city IS NOT NULL;
用 COALESCE 给 NULL 提供展示用的默认值:
SELECT name, COALESCE(city, '未知') AS city, COALESCE(age, 0) AS age FROM students;
COUNT(*) 与 COUNT(列) 的区别:8 名学生里有 6 个填了城市、6 个填了年龄:
SELECT COUNT(*) AS total, COUNT(city) AS with_city, COUNT(age) AS with_age FROM students;
常见坑
- 写 = NULL 判断空值:结果永远是 NULL,查不到任何行,而且数据库不报错,bug 非常隐蔽。一律用 IS NULL。
- 以为 COUNT(列) 等于 COUNT(*):COUNT(列) 跳过 NULL,统计「填写率」时两个值的差正是 NULL 的个数。先想清楚要数什么。
- 聚合结果里 NULL 被悄悄跳过:AVG(age) 只对有年龄的人求平均,如果业务上「未填年龄按 0 算」,结果会偏高。涉及 NULL 的统计口径要在需求里问清楚。
- 空字符串与 NULL 混用:有的系统把「未填」存成 '',有的存 NULL,同一张表里两种都有时 IS NULL 和 = '' 都查不全。入库时统一约定,查询时宁可用 COALESCE(NULLIF(col, ''), '未知') 兜底。
小结
NULL 表示未知,比较得 NULL,判断用 IS NULL / IS NOT NULL,兜底用 COALESCE;COUNT(列) 与聚合函数跳过 NULL。下一节学习给列和表起别名。