ifnull仅适用于单层null兜底,coalesce才是处理多级fallback、跨库兼容及复杂空值逻辑的主力;其核心是严格按从左到右顺序返回首个非null值,且只识别null,不处理空字符串、0或false,参数须类型兼容,否则隐式转换易致逻辑错误、索引失效或前端字段消失。

直接说结论:IFNULL只适合单层兜底,COALESCE才是处理复杂空值的主力;用错函数不是语法报错的问题,而是逻辑悄悄出错、跨库迁移失败、前端字段莫名消失。
COALESCE 多级 fallback 必须按优先级顺序写
它不判断“哪个更合理”,只认“哪个先非 NULL”。比如用户昵称要优先取 nike_name,其次 user_name,最后是 '游客',就得写成:
SELECT COALESCE(nike_name, user_name, '游客') AS display_name FROM users;
如果把 '游客' 放最前,结果永远是它;如果中间插了个可能为 NULL 的表达式(比如 UPPER(nike_name)),一旦 nike_name 是 NULL,UPPER(NULL) 还是 NULL,不影响后续判断——但要注意类型推导是否一致。
- 参数里混用数字和字符串,MySQL 会隐式转成字符串,可能截断或补空格
- 若字段是
INT类型,别写COALESCE(score, 'N/A'),应写COALESCE(score, 0)或显式CAST - 视图定义中必须提前写好
COALESCE,否则下游查出来仍是 NULL,JSON 接口字段直接消失
IFNULL 不能替代 COALESCE 做链式判断
IFNULL 只接受两个参数,硬套多层会嵌套难读且易错:
SELECT IFNULL(nike_name, IFNULL(user_name, '游客')) AS display_name FROM users;
这看起来能跑,但问题不少:
- 可读性差,三层以上就晕
- 无法跨库——PostgreSQL、SQL Server 不认识
IFNULL,视图一迁就崩 - 第二个
IFNULL的user_name若为''(空字符串),它不会被当作 NULL,所以仍返回'',业务上可能等于“没填”,但函数根本不管
真正该用 IFNULL 的场景只有一个:确认字段只可能是 NULL 或有效值,且只需补一个默认值,比如 IFNULL(phone, '未绑定')。
WHERE 和 ORDER BY 里用 COALESCE 要当心索引失效
写 WHERE COALESCE(phone, '') != '' 看似稳妥,实际会让 phone 字段上的索引完全失效,触发全表扫描。
正确做法是拆开判断:
WHERE phone IS NOT NULL AND phone != ''
同理,排序时想让 NULL 排最后,别写:
ORDER BY COALESCE(updated_at, '1970-01-01') DESC
而应写:
ORDER BY updated_at IS NULL, updated_at DESC
- 前者 MySQL 无法利用
updated_at索引 - 后者用布尔表达式排序,索引可用,性能差异可能达百倍
- 如果真要用
COALESCE排序,确保所有参数类型严格一致,否则隐式转换会悄悄改变排序结果
空值判断的前提:先分清 NULL、''、0、FALSE
这是所有问题的起点。写 COALESCE(col, 'default') 却发现还是空,大概率因为 col 是 '' 而不是 NULL;写 IFNULL(status, 'active') 却发现状态显示为 'active',其实原值是 0 或 FALSE ——它们都不是 NULL。
查之前先确认:
SELECT col, col IS NULL, col = '', col = 0 FROM t LIMIT 5;
-
IS NULL是唯一可靠判断方式 - 业务字段设计阶段就该明确:允许 NULL?默认值设什么?空字符串是否合法?
- 上游应用写入时漏传字段,和传了空字符串,语义完全不同,不能靠 SQL 函数后期“擦屁股”











