isnull仅sql server支持,nvl仅oracle支持,mysql用ifnull,跨数据库统一用coalesce;三者均需类型兼容,且空结果集需配合聚合函数才能返回默认值。

直接说结论:ISNULL 是 SQL Server 专用,NVL 是 Oracle 专用,两者不能混用;MySQL 要用 IFNULL,跨数据库统一推荐 COALESCE。
ISNULL 只在 SQL Server 里有效,别在 Oracle 或 MySQL 里写
常见错误是把 SQL Server 的写法直接复制到其他数据库里跑,比如写 SELECT ISNULL(price, 0) FROM products,在 Oracle 会报 ORA-00904: "ISNULL": invalid identifier,在 MySQL 会提示 Unknown function 'ISNULL'(注意:MySQL 有 ISNULL() 函数,但它是判断是否为 NULL 的布尔函数,不是替换函数)。
使用场景:仅限 SQL Server,且只接受两个参数。它不支持嵌套或多个备选值。
-
ISNULL第二个参数类型必须和第一个兼容,否则隐式转换失败(比如ISNULL(date_col, 'N/A')会报错) - 它比
COALESCE略快一点,因为是内置函数,但差异通常可忽略 - 不能用于 UPDATE 的 SET 子句中作为列默认值定义(那是 DEFAULT 约束的事)
NVL 在 Oracle 中必须注意数据类型严格匹配
NVL 看似简单,但最常踩的坑是类型不一致。比如 NVL(salary, '0') ——salary 是 NUMBER 类型,而 '0' 是字符串,Oracle 会尝试隐式转成 NUMBER,看似能过,但一旦 '0.0' 或 'N/A' 就崩了。
正确做法是显式转换:
- 数值字段补默认值:用
NVL(salary, 0)(两边都是 NUMBER) - 字符字段补默认值:用
NVL(name, '未知')(两边都是 VARCHAR2) - 混类型必须强转:比如想把空数字转成文字描述,得写
NVL(TO_CHAR(salary), '未录入') - 聚合后为空更安全:单独查
NVL(rulescore, 0)在无记录时会返回 0 行;但NVL(SUM(rulescore), 0)一定返回 1 行,这才是业务常用写法
MySQL 没有 NVL,别写错成 IFNULL 或 COALESCE
MySQL 不认 NVL,也不认 ISNULL(作为替换函数)。写 IFNULL(price, 0) 是对的,但要注意:
-
IFNULL只接受两个参数,不支持多级 fallback - 如果第二个参数是表达式(如
IFNULL(created_at, NOW())),每次被调用都会重新求值,可能造成非预期时间戳 - 想兼容多种数据库?直接上
COALESCE(price, 0, -1)—— 它在 SQL Server、Oracle、MySQL、PostgreSQL 全都支持,且语义一致:返回第一个非 NULL 值 -
COALESCE所有参数必须可隐式转为同一类型,否则报错,这点比NVL更严格
查询结果整行为空时,NVL/IFNULL 都救不了你
这是最容易被忽略的点:如果 SELECT NVL(name, '匿名') FROM users WHERE id = 123,而表里根本不存在 id = 123 的记录,那这条语句返回 0 行 —— NVL 根本没机会执行。
要确保“哪怕没数据也返回一行”,必须配合聚合函数:
- Oracle:
SELECT NVL(MAX(name), '匿名') FROM users WHERE id = 123 - SQL Server:
SELECT ISNULL(MAX(name), '匿名') FROM users WHERE id = 123 - MySQL:
SELECT IFNULL(MAX(name), '匿名') FROM users WHERE id = 123
因为 MAX() 是聚合函数,即使没匹配行也会返回一行 NULL,这时 NVL 才真正起作用。










