SQL中NULLS LAST并非所有数据库都支持:PostgreSQL、Oracle、SQLite 3.30+、MySQL 8.0+及SQL Server 2022+支持;旧版SQL Server和MySQL 5.7及以前不支持,需用CASE表达式模拟。

SQL中NULLS LAST到底支不支持?先看数据库类型
不是所有数据库都原生支持 NULLS LAST。PostgreSQL、Oracle、SQLite 3.30+ 和 MySQL 8.0+ 支持;SQL Server 2022 起才正式加入,旧版(如 2019 或更早)直接报错 Incorrect syntax near 'NULLS';MySQL 5.7 及之前版本也不识别该语法。
所以别一上来就写 ORDER BY col NULLS LAST——先查你连的是什么版本:
- PostgreSQL:放心用,
NULLS LAST是标准行为之一 - SQL Server:运行
SELECT @@VERSION,确认 ≥ 16.x(即 2022)再用 - MySQL:执行
SELECT VERSION(),≥ 8.0.0 才可用 - 旧环境(尤其 SQL Server 2016/2019):必须换方案,否则查询直接失败
NULLS LAST 在升序和降序中的实际效果
NULLS LAST 的作用是“把 NULL 值排在当前排序方向的末尾”,它不改变字段本身的大小关系,只调整 NULL 的落点:
-
ORDER BY updated_at ASC NULLS LAST→ 非 NULL 时间从小到大,所有 NULL 排在最后 -
ORDER BY score DESC NULLS LAST→ 非 NULL 分数从高到低,所有 NULL 排在最后(即最低分段之后) - 注意:
NULLS LAST和DESC不冲突,但语义上容易误解:它不是“按降序排 NULL”,而是“把 NULL 放在降序结果的最后”
常见错误是以为 DESC NULLS LAST 能让 NULL 显得“更高”,其实它只是确保 NULL 不挤在顶部干扰业务数据顺序。
不支持 NULLS LAST 时的等效替代写法
在 SQL Server 2019 或 MySQL 5.7 这类环境里,得靠表达式“模拟” NULLS LAST 行为。核心思路是:先按“是否为空”分层,再按字段值排序。
升序 + NULL 最后(等效于 ASC NULLS LAST):
ORDER BY CASE WHEN col IS NULL THEN 1 ELSE 0 END, col ASC
降序 + NULL 最后(等效于 DESC NULLS LAST):
ORDER BY CASE WHEN col IS NULL THEN 1 ELSE 0 END, col DESC
关键点:
-
CASE表达式生成一个临时排序键:0 表示非 NULL(优先),1 表示 NULL(靠后) - 第二级排序(
col ASC/DESC)只在同组内生效,不会跨组混序 - 不能写成
ORDER BY ISNULL(col, '9999-12-31')这类补值法——日期补极大值可能溢出,数值补极大数可能影响索引使用
多字段排序时 NULLS LAST 的作用范围
NULLS LAST 只对它紧邻的前一个字段生效,不是全局开关。比如:
ORDER BY status DESC NULLS LAST, created_at ASC NULLS FIRST
这表示:
-
status降序,NULL 排在该字段结果末尾 -
created_at升序,NULL 排在该字段结果开头 - 两字段独立控制,互不影响
容易踩的坑是漏写某个字段后的 NULLS FIRST/LAST,导致部分字段仍按数据库默认规则排(例如 SQL Server 默认升序时 NULL 在最前),结果顺序不一致。跨库迁移时这点尤其致命——同一句 SQL,在 PostgreSQL 里跑得稳,在 SQL Server 旧版里就错位。
真正难处理的,不是语法怎么写,而是团队里有人写了 NULLS LAST,有人没写,又没统一数据库版本,上线后排序突然乱掉,还查不出原因。

















