优先选coalesce,因其是ansi标准、跨数据库兼容、支持多参数、类型推导安全;isnull是sql server私有函数,仅两参数、易静默截断、迁移困难且在where/join中破坏语义。

COALESCE 是 ANSI 标准,ISNULL 是 SQL Server 私有函数
COALESCE 直接写在 SQL-92 标准里,PostgreSQL、MySQL、Oracle、SQL Server 全都原生支持;ISNULL 在 PostgreSQL 里报 ERROR: function isnull(unknown) does not exist,在 MySQL 里根本无法解析。如果你今天用 ISNULL 写了 200 行 SQL,明天换库迁移,基本等于重写。
COALESCE 支持任意多个参数,ISNULL 只能两个
常见需求不是“补一个默认值”,而是“从多个字段里取第一个有效值”——比如优先用 mobile,没有就用 phone,再没有就用 contact_email,最后兜底 '未提供':
COALESCE(mobile, phone, contact_email, '未提供')
用 ISNULL 就得嵌套:ISNULL(mobile, ISNULL(phone, ISNULL(contact_email, '未提供'))),可读性差、易出括号错、调试困难。
COALESCE 类型推导更安全,ISNULL 容易静默截断
当字段类型长度受限时,ISNULL 会无条件按第一个参数定型:
-
ISNULL(name, 'Unknown'):若name是VARCHAR(5),结果强制为VARCHAR(5),'Unknown'被截成'Unkno' -
COALESCE(name, 'Unknown'):类型推导取最大长度,大概率变成VARCHAR(7),不截断
这种截断不会报错,但下游应用收到的是残缺字符串,问题很难定位。
COALESCE 在 WHERE 和 JOIN 中语义更清晰
把 NULL 替换后放进过滤条件,容易破坏逻辑:
-
WHERE ISNULL(o.amount, 0) > 0→ 实际过滤掉所有o.amount IS NULL的行,LEFT JOIN 变相退化成 INNER JOIN -
WHERE COALESCE(o.amount, 0) > 0同样有这问题,但至少你一眼能看出这是“把 NULL 当 0 算”,而 ISNULL 让人误以为只是显示层替换
真正该做的是在 SELECT 中用 COALESCE 填充显示值,在 WHERE 中用 o.amount IS NULL 或 o.amount > 0 显式区分语义。
最常被忽略的一点:COALESCE 不是“更高级的 ISNULL”,它是不同设计目标下的产物——ISNULL 是 T-SQL 里为性能妥协的快捷写法,COALESCE 是标准下为语义明确和跨库兼容做的通用方案。选哪个,取决于你愿不愿意为短期少打几个字符,承担后期迁移、调试、协作的成本。











