COALESCE函数返回参数中第一个非NULL值,用于安全替换NULL(如COALESCE(age, 0)),要求参数类型兼容,支持多数据库,但全为NULL时仍返回NULL。

用 COALESCE 替换 NULL 最直接
当需要把查询结果里的 NULL 统一转成某个默认值(比如 0、'N/A' 或空字符串),COALESCE 是最安全、最通用的选择。它按顺序返回第一个非 NULL 的表达式,且所有参数类型需兼容。
常见错误是传入类型不一致的参数,比如 COALESCE(age, 'unknown') 在严格模式下可能报错(age 是 INT,'unknown' 是字符串);应统一为字符串或显式转换:
SELECT COALESCE(CAST(age AS TEXT), 'unknown') FROM users;
- 支持任意数量参数,但建议只传 2–3 个,避免逻辑难读
- 比
ISNULL(SQL Server)或NVL(Oracle)更跨数据库,PostgreSQL/MySQL/SQLite 都支持 - 注意:如果所有参数都是
NULL,结果仍是NULL
用 WHERE ... IS [NOT] NULL 过滤 NULL 行
不是所有场景都需要替换 NULL,有时只需排除或聚焦含 NULL 的记录。此时不能用 = NULL 或 != NULL —— 它们永远返回 FALSE 或 UNKNOWN,查不到任何数据。
正确写法只有两种:
SELECT * FROM orders WHERE shipped_date IS NULL;<br>SELECT * FROM orders WHERE shipped_date IS NOT NULL;
-
IS NULL和IS NOT NULL是标准 SQL,所有主流数据库都支持 - 在
WHERE中对可空列加IS NULL条件时,若该列无索引,性能可能较差;必要时可建函数索引(如 PostgreSQL 的CREATE INDEX ON orders ((shipped_date IS NULL))) - 注意:
NULL不参与IN判断,WHERE status IN ('shipped', NULL)等价于WHERE status = 'shipped',NULL被静默忽略
聚合函数自动忽略 NULL,但得留意 COUNT 的例外
像 SUM、AVG、MAX、MIN 这些聚合函数默认跳过 NULL 值,行为符合直觉。但 COUNT 很特殊:COUNT(*) 统计所有行,而 COUNT(column) 只统计该列非 NULL 的行数。
例如想查“有邮箱的用户数”,必须写:
SELECT COUNT(email) FROM users;
而不是:
SELECT COUNT(*) FROM users WHERE email IS NOT NULL; -- 多此一举,且可能慢
-
COUNT(email)更简洁,执行计划通常也更优(尤其带索引时) - 如果误用
COUNT(email)却忘了email列本身允许NULL,结果会比预期少——这是最容易被忽略的语义偏差 -
GROUP BY后的聚合同理,COUNT(col)在每组内独立计非空值
ORDER BY 中 NULL 的排序位置由数据库决定
NULL 在排序时既不大于也不小于任何值,所以不同数据库默认把它排在最前(PostgreSQL、SQL Server)或最后(MySQL、Oracle)。这会导致分页或取 Top N 时结果不一致。
显式控制方式如下:
-- PostgreSQL / MySQL 8.0+ / SQL Server<br>SELECT * FROM products ORDER BY price ASC NULLS FIRST;<br><br>-- MySQL 5.7 或旧版,用 IF/COALESCE 模拟<br>SELECT * FROM products ORDER BY (price IS NULL) DESC, price ASC;
-
NULLS FIRST/NULLS LAST是 SQL:2003 标准,但并非所有数据库都支持(如 SQLite 不支持) - 在
ORDER BY中混用NULL处理和业务逻辑(比如把NULL当最高优先级)时,务必在注释里写清意图,否则后续维护容易误解
NULL 的本质是“缺失值”而非“空值”,所有处理都围绕这个前提展开。最常踩的坑不是语法写错,而是混淆了“过滤 NULL”“替换 NULL”和“统计 NULL”的语义边界——尤其在嵌套子查询或 JOIN 后,NULL 可能从多个来源混入,得一层层确认来源再选对应方法。

















