首页/数据/SQL 速查/IS NULL / IS NOT NULL 判空

IS NULL / IS NOT NULL 判空

NULL 表示“未知”,不能用等号判断;IS [NOT] NULL 是可靠的判空方式,也是计数与条件过滤中常见的坑位。

SQL 速查数据更新于 2026-10-13

IS NULL 是什么

NULL 表示未知或缺失,不能用等号判断:a = NULL 的结果是 UNKNOWN,而 WHERE 只保留求值为 TRUE 的行,所以这类写法永远查不出数据却也不报错。正确写法是 IS NULL 与 IS NOT NULL。NULL 还会影响统计:COUNT(col) 会跳过 NULL,AVG 的分母是非 NULL 行数,NULL 参与算术或字符串拼接通常让结果也变成 NULL。理解这三条规则,才能写对判空、补数据和缺失率统计。

基本信息

判空写法IS NULL 与 IS NOT NULL,都是标准写法
错误写法= NULL、<> NULL,结果恒为 UNKNOWN,永远不成立
聚合影响COUNT(col)、SUM、AVG、MIN、MAX 都忽略 NULL
运算影响NULL 参与算术得到 NULL;MySQL 的 CONCAT 遇 NULL 得 NULL
唯一索引多个 NULL 通常互不冲突,唯一约束对 NULL 不生效
平台差异PostgreSQL 另有 IS DISTINCT FROM 做 NULL 安全比较

典型使用场景

  • 找缺失数据:手机号、邮箱为空的行,用来评估字段填充率
  • 补数据前置检查:更新前先确认到底有多少行真的需要补
  • 统计非空量:COUNT(col) 与 COUNT(*) 相减得到缺失行数
  • 区分未填与空串:业务上要区分 NULL 与 '' 时先统一口径
  • 排除缺失再运算:WHERE col IS NOT NULL 后再做函数计算,避免整列变 NULL
  • 分组观察:NULL 会被归到同一组,用来发现某维度有大量缺失

示例

示例
SELECT * FROM users WHERE phone IS NULL;       # 手机号缺失的行
SELECT * FROM users WHERE phone IS NOT NULL;   # 手机号已填的行

SELECT COUNT(*)                AS all_rows,
       COUNT(phone)            AS has_phone,
       SUM(phone IS NULL)      AS null_phone,    # MySQL:布尔值即 0/1
       COUNT(*) - COUNT(phone) AS missing_phone
FROM users;

-- PostgreSQL:布尔值不能直接求和,先转换
SELECT SUM((phone IS NULL)::int) FROM users;

NULL 在各处的表现

位置表现注意
比较 a = NULL结果为 UNKNOWN永远不成立,必须用 IS NULL
算术 NULL + 1结果为 NULL金额计算前先兜底
字符串拼接MySQL 得 NULL,PG 的 concat 忽略统一用 COALESCE 兜底
聚合 COUNT(col)跳过 NULL与 COUNT(*) 结果不同
GROUP BY多个 NULL 归为同一组WHERE col = NULL 取不出这一组
唯一索引多个 NULL 互不冲突需要强唯一时要额外约束
PostgreSQL 提供 IS DISTINCT FROM:a IS DISTINCT FROM b 在其中一个为 NULL 时返回 true,用于 NULL 安全的差异比对,比 <> 更可靠。
排序时 NULL 的位置由数据库决定:MySQL 把 NULL 视为最小排在最前,PostgreSQL 默认排在最后;需要固定位置时 PostgreSQL 用 NULLS FIRST / LAST,MySQL 用 ISNULL(col) 表达式参与排序。
WHERE col <> 'x' 会漏掉 col 为 NULL 的行。业务上如果要把缺失行也算作不符合条件,必须显式写上 OR col IS NULL。
NULL 与空串不是一回事:空串长度为零、参与比较与拼接都有确定行为,建模时要提前决定是否禁止空串,避免同一语义出现两种存法。

判空实践要点

  • 建表时明确每列的可空性:关键字段加 NOT NULL 约束,能挡掉一批脏数据
  • 用默认值代替 NULL 是常见取舍:数字用 0、字符串用空串,代价是失去未填与已填的区分
  • 缺失率统计先定口径:分母是所有行还是符合条件的行为,写进报表说明
  • 判空与索引:NULL 占比低时 IS NULL 可能走索引,占比高时优化器倾向全表扫描
  • 接口层统一 NULL 的表示:JSON 里是 null 还是缺字段,前后端要提前对齐
  • 补数据脚本先备份原值:UPDATE 补 NULL 字段前确认影响行数,并保留回滚依据
判断一个列是否真的缺数据,不要只看 IS NULL:业务上未填也可能写成空串或 0,统计前先确认历史数据的实际写法。
排查查询结果为空时先怀疑 NULL:条件里出现 <>、NOT IN、NOT LIKE 这些写法时,都要确认相关列是否可能为 NULL,这是最常见的误判来源。
统计缺失率时用 COUNT(*) 减 COUNT(col) 最直观,也避开了布尔表达式在不同数据库写法上的差异,跨库 SQL 更省事。
在接口契约里把 NULL 的传输形式约定清楚能省很多事:是返回 null、返回空串还是省略字段,前后端提前对齐,比事后逐个字段排查高效得多。

易错点

  • WHERE phone = NULL 不报错但永远返回空集,是新手与迁移场景的高频错误
  • NOT (a = b) 与 a <> b 在遇到 NULL 时都为 UNKNOWN,取反逻辑要按三值逻辑重新核对
  • 用 COUNT(col) 当行数用,列里含 NULL 时统计结果偏小
  • 对含 NULL 的列做算术或拼接后忘记兜底,整列结果变成 NULL 却查不出原因
  • 以为唯一索引能拦住重复的 NULL,实际多条 NULL 可以共存,需要额外约束或业务校验

数据来源与参考

  • MySQL 8.0 Reference Manual · Working with NULL Values
  • PostgreSQL Documentation · IS NULL
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌