nullif 是绕过除零异常最轻量、最标准的做法,它在分母为0时返回null使除法结果为null而非报错,兼容所有主流数据库且语义清晰。

NULLIF 能在除法前主动把分母变成 NULL,从而让整个表达式返回 NULL 而不是报错 —— 这是绕过除零异常最轻量、最标准的做法。
为什么 NULLIF 是除零防护的第一道防线
数据库执行 10 / 0 时会直接抛出错误(如 PostgreSQL 的 division by zero,SQL Server 的 Msg 8134),查询中断。而 NULLIF(divisor, 0) 在 divisor 为 0 时返回 NULL,再参与除法:10 / NULLIF(0, 0) → 10 / NULL → 结果为 NULL,不报错。
- 它不依赖 CASE 或子查询,写法简洁,语义清晰:“如果分母是 0,就当作不存在”
- 所有主流数据库(PostgreSQL、SQL Server、Oracle、MySQL 8.0+、SQLite)都支持
NULLIF,兼容性好 - 相比
CASE WHEN divisor = 0 THEN NULL ELSE numerator / divisor END,NULLIF更少出错、更易读
NULLIF 必须和除法一起用,单独用没意义
NULLIF 本身只做“相等则转 NULL”,不改变数据类型或触发计算。它只有嵌入到除法表达式中才起防护作用:
SELECT amount / NULLIF(quantity, 0) AS unit_price, total / NULLIF(items_sold, 0) AS avg_per_order FROM sales;
- 错误写法:
SELECT NULLIF(quantity, 0) FROM sales—— 只是把 0 换成 NULL,没解决后续除法问题 - 不能写成
NULLIF(amount / quantity, 0)—— 除法已先执行,崩溃发生在NULLIF之前 - 注意:如果
quantity列本身含NULL,NULLIF(quantity, 0)仍返回NULL,所以amount / NULL仍是NULL,符合预期
和 COALESCE 配合控制 NULL 的最终呈现
NULLIF 把除零转成 NULL,但业务上可能需要显示 0、'N/A' 或跳过该行。这时接一个 COALESCE 或 CASE:
SELECT COALESCE(amount / NULLIF(quantity, 0), 0) AS unit_price, COALESCE(total / NULLIF(items_sold, 0), -1) AS avg_per_order FROM sales;
-
COALESCE是安全的,因为它的参数按顺序求值,前面已是NULL才会看后面 - 避免用
ISNULL()(SQL Server 专属)或IFNULL()(MySQL)替代COALESCE,它们不跨数据库兼容 - 如果想过滤掉整行(比如不要任何单位价为 NULL 的记录),得在
WHERE里写quantity != 0,而不是依赖NULLIF—— 因为NULLIF不影响行存在性
真正容易被忽略的是:当分母来自聚合函数(如 SUM())或窗口函数时,NULLIF 依然有效,但要注意空组的聚合结果本身就是 NULL,此时 NULLIF(SUM(x), 0) 仍返回 NULL,不会误判为 0 —— 这点恰恰是它比手工 CASE 更鲁棒的地方。











