如何使用NULLS FIRST或NULLS LAST函数在Oracle中设置空值排序优先级?
- 内容介绍
- 文章标签
- 相关推荐
本文共计884个文字,预计阅读时间需要4分钟。
Oracle数据库中空值默认排序行为为不确定,升序(ASC)时排最后,降序(DESC)时排最前。但无法满足业务中统一把NULL放最前/最后的需求——必须显式使用+ `NULLS FIRST` 或 `NULLS LAST` 控制排序。
Oracle 默认空值排序逻辑是什么
Oracle 把 NULL 视为“未知最大值”,不是 0、不是空字符串、也不等于自身。这导致:
-
ORDER BY col ASC:所有NULL排在非空值之后(即末尾) -
ORDER BY col DESC:所有NULL排在非空值之前(即开头) - 这种行为不可靠 —— 它依赖于排序方向,且和多数前端展示逻辑(比如“空姓名置顶”)冲突
用 NULLS FIRST 强制空值排最前
无论升序还是降序,加 NULLS FIRST 就能确保所有 NULL 记录出现在结果集头部:
SELECT * FROM employees ORDER BY hire_date NULLS FIRST;
SELECT * FROM employees ORDER BY hire_date DESC NULLS FIRST;
注意:NULLS FIRST 不改变字段本身的排序方向(ASC 还是 DESC),只决定 NULL 的位置优先级。
- 常见误写:
ORDER BY col ASC NULLS FIRST是合法的,但容易让人误以为ASC和NULLS FIRST冲突 —— 实际不会,NULLS FIRST优先级更高 - 如果字段有索引,
NULLS FIRST可能无法走索引范围扫描(尤其复合索引中该字段非首列),需结合执行计划验证
用 NULLS LAST 强制空值排最后
这是更常用的做法,尤其适配“补全数据后置底”的业务场景:
SELECT * FROM products ORDER BY price DESC NULLS LAST;
即使按价格降序,价格为空的商品也不会挤到顶部,而是沉到底部。
-
NULLS LAST在分页查询中更安全:避免第一页全是NULL数据,导致有效数据被压到后续页 - MyBatis-Plus 3.4+ 提供了
orderByAscNullsLast()等封装方法,底层仍是拼NULLS LAST,但要注意它只对 Oracle 生效,切换数据库需额外适配 - Hibernate HQL 4.2+ 才支持
NULLS LAST,旧版本必须改用原生 SQL 或COALESCE替代
替代方案:不用 NULLS FIRST/LAST 怎么办
某些老旧系统或 ORM 层不支持该语法时,可用函数兜底,但代价明显:
-
NVL(col, TO_DATE('1900-01-01', 'YYYY-MM-DD')):把空日期转成极小值,配合ASC实现“空值靠前”,但类型要匹配、且可能污染统计逻辑 -
CASE WHEN col IS NULL THEN 0 ELSE 1 END, col:用排序权重拆成两层,可读性差、性能略低,且CASE表达式无法利用普通索引 - 千万别用
col = col或col IS NOT NULL做排序条件 —— 这会强制全表扫描,且语义不清
真正需要跨数据库兼容时,别硬套 Oracle 语法;要么在应用层过滤/补位,要么接受不同库的空值行为差异 —— 毕竟 NULLS FIRST/LAST 是 Oracle 特性,不是 SQL 标准。
本文共计884个文字,预计阅读时间需要4分钟。
Oracle数据库中空值默认排序行为为不确定,升序(ASC)时排最后,降序(DESC)时排最前。但无法满足业务中统一把NULL放最前/最后的需求——必须显式使用+ `NULLS FIRST` 或 `NULLS LAST` 控制排序。
Oracle 默认空值排序逻辑是什么
Oracle 把 NULL 视为“未知最大值”,不是 0、不是空字符串、也不等于自身。这导致:
-
ORDER BY col ASC:所有NULL排在非空值之后(即末尾) -
ORDER BY col DESC:所有NULL排在非空值之前(即开头) - 这种行为不可靠 —— 它依赖于排序方向,且和多数前端展示逻辑(比如“空姓名置顶”)冲突
用 NULLS FIRST 强制空值排最前
无论升序还是降序,加 NULLS FIRST 就能确保所有 NULL 记录出现在结果集头部:
SELECT * FROM employees ORDER BY hire_date NULLS FIRST;
SELECT * FROM employees ORDER BY hire_date DESC NULLS FIRST;
注意:NULLS FIRST 不改变字段本身的排序方向(ASC 还是 DESC),只决定 NULL 的位置优先级。
- 常见误写:
ORDER BY col ASC NULLS FIRST是合法的,但容易让人误以为ASC和NULLS FIRST冲突 —— 实际不会,NULLS FIRST优先级更高 - 如果字段有索引,
NULLS FIRST可能无法走索引范围扫描(尤其复合索引中该字段非首列),需结合执行计划验证
用 NULLS LAST 强制空值排最后
这是更常用的做法,尤其适配“补全数据后置底”的业务场景:
SELECT * FROM products ORDER BY price DESC NULLS LAST;
即使按价格降序,价格为空的商品也不会挤到顶部,而是沉到底部。
-
NULLS LAST在分页查询中更安全:避免第一页全是NULL数据,导致有效数据被压到后续页 - MyBatis-Plus 3.4+ 提供了
orderByAscNullsLast()等封装方法,底层仍是拼NULLS LAST,但要注意它只对 Oracle 生效,切换数据库需额外适配 - Hibernate HQL 4.2+ 才支持
NULLS LAST,旧版本必须改用原生 SQL 或COALESCE替代
替代方案:不用 NULLS FIRST/LAST 怎么办
某些老旧系统或 ORM 层不支持该语法时,可用函数兜底,但代价明显:
-
NVL(col, TO_DATE('1900-01-01', 'YYYY-MM-DD')):把空日期转成极小值,配合ASC实现“空值靠前”,但类型要匹配、且可能污染统计逻辑 -
CASE WHEN col IS NULL THEN 0 ELSE 1 END, col:用排序权重拆成两层,可读性差、性能略低,且CASE表达式无法利用普通索引 - 千万别用
col = col或col IS NOT NULL做排序条件 —— 这会强制全表扫描,且语义不清
真正需要跨数据库兼容时,别硬套 Oracle 语法;要么在应用层过滤/补位,要么接受不同库的空值行为差异 —— 毕竟 NULLS FIRST/LAST 是 Oracle 特性,不是 SQL 标准。

