SQL 中 IS NULL 与 = NULL 的本质差异

12次阅读

IS NULL 是标准且正确的空值判断方式,因为 NULL 不是值而是缺失标记,= NULL 永远返回 UNKNOWN,WHERE 中被过滤;IS NULL 和 IS NOT NULL 是专用于检测 NULL 语义的真值测试谓词。

SQL 中 IS NULL 与 = NULL 的本质差异

sql 中,IS NULL 是标准、正确的空值判断方式,而 = NULL 永远返回 UNKNOWN(在 WHERE 或 ON 条件中等效于 FALSE),查不到任何结果——这不是语法错误,而是由 SQL 三值逻辑(TRUE/FALSE/UNKNOWN)决定的本质行为。

NULL 不是值,而是一种“缺失标记”

SQL 中的 NULL 表示“未知”或“不适用”,它不等于任何东西,包括它自己。因此:

  • NULL = NULL 的结果不是 TRUE,而是 UNKNOWN
  • NULL = 5NULL = ''NULL = NULL 全部返回 UNKNOWN
  • WHERE 子句只保留计算结果为 TRUE 的行,自动过滤掉 FALSE 和 UNKNOWN

IS NULL 是专门设计的谓词,用于检测缺失状态

不同于比较运算符(=、!=、> 等),IS NULLIS NOT NULL 是 SQL 标准定义的**真值测试谓词**,直接作用于 NULL 的语义属性:

  • column IS NULL → 返回 TRUE 当且仅当 column 确实为 NULL
  • column IS NOT NULL → 返回 TRUE 当且仅当 column 有确定的非空值
  • 它们不参与值比较,不触发三值逻辑的“传染性”,行为确定可靠

常见误用与实际影响

WHERE age = NULL 看似直觉,但实际等价于 WHERE UNKNOWN,整张表被跳过。例如:

  • 表 users 有 100 行,其中 3 行 age 为 NULL → select * FROM users WHERE age = NULL 返回 0 行
  • 正确写法必须是 SELECT * FROM users WHERE age IS NULL → 返回那 3 行
  • 某些数据库(如 postgresql)会直接拒绝 = NULL 并报错;mysql 和 SQL Server 虽允许,但逻辑不变

扩展:如何安全地处理 NULL 比较

若需逻辑上“把 NULL 当作相同值来对待”(如去重、连接),不能依赖 =,而应使用:

  • IS NOT DISTINCT FROM(标准 SQL,PostgreSQL/SQL Server 支持):可安全比较两个可能为 NULL 的表达式
  • COALESCE(a, 'default') = COALESCE(b, 'default'):将 NULL 映射为统一占位值再比较(注意类型和默认值合理性)
  • 连接时用 ON a.id = b.id OR (a.id IS NULL AND b.id IS NULL) 显式覆盖 NULL 匹配场景
text=ZqhQzanResources