NULLIF本身不防止除零错误,它仅将分母为0转为NULL;真正避免报错的是SQL标准中“任何数除以NULL返回NULL”的规则,因此必须将NULLIF(分母, 0)置于除法右侧分母位置,且须配合COALESCE或CASE处理NULL语义。

NULLIF本身不防止除零错误,它只是把分母为0的值变成NULL;真正让查询不崩的是SQL标准规定——任何数除以NULL结果为NULL,而非报错。
NULLIF(分母, 0)必须写在除法右侧分母位置
常见错误是套错位置或参数顺序颠倒。只要分母还没参与运算,就得先被NULLIF处理。
- ✅ 正确:
SELECT revenue / NULLIF(cost, 0)——cost为0时整条除法得NULL - ❌ 错误:
SELECT NULLIF(revenue, 0) / cost—— 分母仍是cost,0照旧触发报错 - ❌ 错误:
SELECT revenue / NULLIF(0, cost)—— 这永远返回cost(除非cost本身就是0) - ⚠️ 注意:
NULLIF第二个参数必须是字面量0,不是0.0或变量,否则浮点比较可能失效
聚合后除法(如SUM/AVG)必须对聚合结果用NULLIF
GROUP BY场景下,除零总在聚合完成之后爆发,因为SUM(impressions)算出来是0,再除就崩。不能对原始列用NULLIF,得包住整个聚合表达式。
- ✅ 正确:
SUM(conversions) / NULLIF(SUM(impressions), 0) - ❌ 错误:
SUM(conversions) / NULLIF(impressions, 0)—— 这是对每行做判断,和分母是否为0无关 - ❌ 错误:
SUM(NULLIF(impressions, 0))—— 这改的是分子逻辑,分母还是SUM(impressions),照样为0 - ⚠️ 特别注意:MySQL在
STRICT_TRANS_TABLES模式下仍可能报错,此时需加COALESCE(..., 0)兜底
得到NULL后别直接用,业务语义必须显式处理
NULLIF只解决“不断查询”,不解决“怎么呈现”。前端看到NULL常会出错,而填0又可能扭曲指标含义。
- 想显示0%:用
COALESCE(numerator * 100.0 / NULLIF(denominator, 0), 0.0)(乘100.0防整数截断) - 想标异常:用
CASE WHEN numerator / NULLIF(denominator, 0) IS NULL THEN 'div_by_zero' ELSE 'ok' END - 别写
COALESCE(NULLIF(denominator, 0), 0)——这等于把NULL换回0,又回到除零 - WHERE中慎用:写
WHERE result IS NOT NULL才能过滤掉无效计算行;result != 0会漏掉NULL,也判不出负数
最麻烦的从来不是写对NULLIF,而是想清楚:这个除法在业务里到底该返回什么——NULL、0、默认值,还是该由上游拦住?











