
IS NULL 判断字段是否为 NULL 值
IS NULL 是 SQL 中唯一可靠判断字段值是否为 NULL 的方式。因为 NULL 表示“未知”,不是值,所以不能用 = 或 != 比较——column = NULL 永远返回 UNKNOWN(在 WHERE 中等价于 FALSE),查不到任何结果。
用 WHERE column IS NULL 才能命中真正为 NULL 的行 WHERE column = ” 只匹配空字符串,和 NULL 完全无关 字符串、数字、日期字段都适用,语法一致,不因类型变化 在索引列上使用 IS NULL 通常能走索引(取决于数据库和索引定义,MySQL 5.7+、PostgreSQL、SQL Server 均支持) SELECT * FROM users WHERE email IS NULL;
IS NOT NULL 排除 NULL 值但不等于“有内容”
IS NOT NULL 筛出非 NULL 的行,但它不保证字段有意义:空字符串 ”、全空格、零值 0、默认时间 ‘0001-01-01’ 都算“非 NULL”,但业务上可能仍是无效数据。
若需排除“空内容”,得组合判断,比如:WHERE email IS NOT NULL AND TRIM(email) != ” NOT (column IS NULL) 语义等价,但可读性差,不推荐 某些 ORM(如 Django ORM)生成的 __isnull=False 底层就是 IS NOT NULL,要注意它不自动过滤空字符串 PostgreSQL 对 IS NOT NULL 优化较好;MySQL 在 MyISAM 引擎下对 IS NOT NULL 的索引使用略保守(InnoDB 无此问题)
别把 NULL 和空字符串、零值混为一谈
这是最常踩的坑:数据库里 NULL、”、0、FALSE 是四个独立状态,语义完全不同。
插入时显式写 NULL(不赋值或写 NULL)才存为 NULL;多数 ORM 默认不设值即为 NULL,但有些框架(如 Laravel Eloquent)会把空表单转成 ” 或 0 COALESCE(column, ‘N/A’) 能把 NULL 转成默认值,但对 ” 无效——得先用 NULLIF(column, ”) 把空字符串转成 NULL 再处理 聚合函数如 COUNT(column) 自动忽略 NULL,但不会忽略 ” 或 0 ORDER BY 中,NULL 默认排最前(ASC)或最后(DESC),行为因数据库而异(PostgreSQL 可用 NULLS FIRST/LAST 显式控制)
WHERE 中混合 NULL 判断时注意逻辑短路失效
SQL 标准不保证布尔表达式短路,尤其涉及 OR 和 AND 时,NULL 可能让整个条件不可预测。
WHERE status = ‘active’ OR other_col IS NULL:如果 status 是 NULL,左边为 UNKNOWN,整体结果取决于右边,但执行计划可能意外跳过索引 更危险的是:WHERE col != ‘X’ OR col IS NULL ——本意是“不是 X 或为空”,但 col != ‘X’ 在 col 为 NULL 时是 UNKNOWN,不触发 OR 的真值传播,实际漏掉 NULL 行 安全写法是显式拆开:WHERE col IS NULL OR col != ‘X’ 复杂条件建议用 CASE WHEN 或提前用 COALESCE 归一化,比堆 IS NULL 更可控
NULL 的语义是“缺失值”,不是“未初始化”也不是“默认值”。一旦表设计没明确区分 NULL 和空字符串,后续所有查询、统计、导出都容易出偏差——这点在迁移旧系统或对接第三方数据时最容易被忽略。

评论(0)