首页/数据/SQL 速查/NULL 安全比较:<=> 与 IS DISTINCT FROM

NULL 安全比较:<=> 与 IS DISTINCT FROM

普通等号遇到 NULL 得 UNKNOWN,需要 NULL 安全相等时:MySQL 用 <=>,标准与 PostgreSQL 用 IS [NOT] DISTINCT FROM。

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

空值安全比较

普通等号遇到空值得到的是未知,不是成立也不是不成立,因此比较两个可能为空的列时用等号会漏掉「两个都是空」的行。需要把空值当作一个可比较的值时,要用空值安全的比较写法:MySQL 提供了专用运算符,结果恒为零或一;标准 SQL 与 PostgreSQL 用专门的判定表达式,读起来更接近自然语言。这类比较常出现在去重、版本比对、可空连接键匹配的场景里。

基本信息

适用平台MySQL 8.0 / PostgreSQL 12 及以上
MySQL 写法空值安全运算符,返回零或一,不会返回未知
PostgreSQL 写法判定表达式的两种形式,分别表示相等与不等
用途匹配可空连接键、按整行去重、版本比对
语义差别空值与空值在这种比较下被视为相等

典型使用场景

  • 可空连接键匹配:两侧都可能为空时仍希望匹配上
  • 数据比对:找出两行内容不同的记录,包括空值与值之间的差异
  • 去重判断:把空值当成一个确定的取值参与去重
  • 变更检测:比较新旧快照的字段是否真的不同
  • 同步任务:判断源端与目标端的字段值是否一致

两库写法与结果

两库写法与结果
-- MySQL:空值安全运算符,结果恒为 0 或 1
SELECT NULL <=> NULL,      -- 1,两个空被视为相等
       1    <=> NULL,      -- 0,值与非空不相等
       'a'  <=> 'a';       -- 1

-- PostgreSQL:判定表达式
SELECT NULL IS NOT DISTINCT FROM NULL;   -- true,表示两者不区分
SELECT 1    IS DISTINCT FROM NULL;       -- true,表示两者有区别
SELECT 1    IS DISTINCT FROM 1;          -- false

-- 典型用法:可空键做连接
SELECT a.id, b.remark
FROM a
LEFT JOIN b ON a.code IS NOT DISTINCT FROM b.code;   -- 空值也能匹配上

-- 数据比对:找出两版内容确实不同的记录
SELECT id FROM v1 JOIN v2 USING (id)
WHERE v1.val IS DISTINCT FROM v2.val;

比较结果对照

左值右值普通等号空值安全比较
11成立成立
12不成立不成立
1空值未知不成立
空值空值未知成立
空值空值(取不等形式)未知不成立
把空值安全比较用在连接条件上时,空值行会互相匹配上。这在按编号对齐的数据里通常是错的,只有业务确实需要「缺失值也视为同组」时才使用。
空值安全运算符是 MySQL 方言,换库时要改写成标准的判定表达式。写数据同步逻辑时统一用标准写法,迁移时就不需要逐条检查。

易错点

  • 用普通等号比较可空列,两个都是空值的行既不成立也不报错,结果静默漏掉
  • 把空值安全比较用在编号类连接键上,空值行被匹配到一起,产生脏关联
  • 从 MySQL 迁移时直接照搬空值安全运算符,PostgreSQL 报语法错误,应改为判定表达式
  • 以为判定表达式可以用在索引条件上:空值参与比较时索引利用率下降,大表上要评估
  • 去重时依赖普通等号排除空值行,导致重复记录清不掉

数据来源与参考

  • MySQL 8.0 Reference Manual · Comparison Functions and Operators
  • PostgreSQL Documentation · Comparison Operators
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌