用 COALESCE
替代直接比较 NULL
MySQL 中
NULL不等于任何值,包括它自己,所以
col = NULL或
col != NULL永远返回
FALSE。常见错误是写
WHERE status != 'done'但漏掉
status IS NULL的行。
健壮写法优先用
COALESCE把空值转为可控默认值:
SELECT COALESCE(price, 0) * quantity AS total FROM orders;
多个备选时可链式 fallback:
COALESCE(a, b, c, 0)从左到右取第一个非
NULL值。
注意:
COALESCE所有参数必须类型兼容,否则隐式转换可能出错(比如字符串和数字混用)。
IFNULL
和 NULLIF
的适用边界
IFNULL(expr1, expr2)是
COALESCE的双参数简化版,性能略优,但仅支持两个参数;
NULLIF(a, b)在
a = b时返回
NULL,否则返回
a,常用于“规避除零”或“条件清空字段”:
SELECT id, NULLIF(status, 'pending') AS safe_status FROM tasks;当
status = 'pending'→ 返回
NULL其他值(含
NULL)→ 原样返回
别误用
NULLIF判断空值:它不处理
NULL输入的逻辑分支,
NULLIF(col, NULL)永远返回
col(因为
NULL = NULL不成立)。
聚合函数中 NULL
的默认行为与陷阱
SUM()、
AVG()、
COUNT()等天然跳过
NULL,这是合理设计,但容易引发误解:
COUNT(col)只统计非
NULL行,
COUNT(*)统计所有行
AVG(col)分母是
COUNT(col),不是
COUNT(*);若全为
NULL,结果为
NULL,不是
0想强制包含空值参与计算?先用
COALESCE转换:
AVG(COALESCE(score, 0))
聚合前没清洗
NULL,可能导致业务指标偏差——比如平均分被低估(因缺考者被完全排除),而实际需要的是“全员平均(缺考记 0)”。
存储过程/函数里避免 NULL
传播中断逻辑
在自定义函数中,若参数声明为
IN且传入
NULL,后续表达式一旦涉及
NULL运算(如
+ - * /、字符串拼接),结果大概率变
NULL,且不会报错,静默失效:
DELIMITER $$ CREATE FUNCTION calc_bonus(salary DECIMAL(10,2), rate DECIMAL(3,2)) RETURNS DECIMAL(10,2) BEGIN RETURN salary * rate; -- 若 salary 或 rate 是 NULL,结果必为 NULL END$$ DELIMITER ;
解决方法:显式校验 + 默认兜底
用IFNULL(salary, 0)或
COALESCE(salary, 0)强制转义 对关键参数加前置判断:
IF salary IS NULL THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'salary cannot be NULL';
最易忽略的是:函数返回类型声明为
NOT NULL时,若内部逻辑返回
NULL,MySQL 不报错也不截断,而是按类型默认值填充(如数值型填
0),掩盖问题。
