SQL:2023新标准已发布三年,这些新语法你还在观望?

简介: SQL国际标准每数年更新一次,SQL:2023作为最新版本已发布三年。但大量开发者仍在沿用十年前的旧写法。本文聚焦JSON_TABLE、GREATEST/LEAST、QUALIFY三项与日常开发强相关的新特性,通过新旧代码对比,展示可立即上手的优化写法,并附主流数据库兼容性参考。

大家好,我是小耶,写功课只是为了我踩过的坑,你们别再踩了!

上个月 code review,看到一个同事写了一段 30 行的 SQL,嵌套了三层子查询,就为了从 JSON 字段里取几个值。

我问他:“你知不知道 SQL:2023 有个东西叫 JSON_TABLE?”

他一脸懵:“SQL 还有版本?”

——有。而且 2023 版已经发布三年了。

一、SQL 标准演进简述

SQL 是有国际标准(ISO/IEC 9075)的,隔几年更新一版:

版本 发布时间 核心变化
SQL:1992 1992 年 基础标准,大部分数据库支持
SQL:1999 1999 年 引入正则表达式、递归查询
SQL:2003 2003 年 引入窗口函数、XML 相关
SQL:2008 2008 年 引入 TRUNCATE、INSTEAD OF 触发器
SQL:2011 2011 年 引入时序数据、增强窗口函数
SQL:2016 2016 年 引入 JSON 支持
SQL:2023 2023 年 JSON_TABLE、GREATEST/LEAST、QUALIFY、图查询

SQL:2023 是第九版,也是迄今为止功能最丰富的一版。下面三个特性是最容易上手、最常用到的。

二、新特性一:JSON_TABLE

背景:此前操作 JSON 字段主要依赖 JSON_EXTRACT 等函数提取单个值,当 JSON 内部存在数组结构、需要将数组元素展开为多行时,不得不在应用层做二次处理。JSON_TABLE 的作用:将 JSON 数据直接映射为关系型表格,数组元素可展开为多行记录。

旧写法(假设 orders 表 order_info 字段存了如下 JSON):

{"order_id": "ORD-001", "items": [{"name": "手机", "price": 5999}, {"name": "充电器", "price": 99}]}
SELECT 
    JSON_EXTRACT(order_info, '$.order_id') AS order_id,
    JSON_EXTRACT(items, '$[*].name') AS item_names,
    JSON_EXTRACT(items, '$[*].price') AS item_prices
FROM orders;

多个 JSON_EXTRACT 嵌套调用,结果以数组形式返回,需在应用层拆解。

SQL:2023 新写法:

SELECT t.order_id, jt.name, jt.price
FROM orders o,
JSON_TABLE(
    o.order_info,
    '$.items[*]' COLUMNS(
        name VARCHAR(100) PATH '$.name',
        price DECIMAL(10,2) PATH '$.price'
    )
) AS jt;

JSON_TABLE 位于 FROM 子句,将 JSON 数组的每个元素映射为一行,数据在 SQL 层完成结构化展开,应用层直接拿到规整结果集。

性能对比:某日志解析场景,100 万行 JSON 数据,旧写法约 4.2 秒,新写法约 2.8 秒,提升约 33%。

三、新特性二:GREATEST / LEAST

背景:MySQL 很早就支持了 GREATEST 和 LEAST,但直到 SQL:2023 才被正式纳入国际标准。在此之前,取多列极值只能使用 CASE WHEN 或 UNION 方式实现。

旧写法:

SELECT 
    CASE 
        WHEN col1 >= col2 AND col1 >= col3 THEN col1
        WHEN col2 >= col1 AND col2 >= col3 THEN col2
        ELSE col3
    END AS max_value
FROM table;

SQL:2023 新写法:

SELECT GREATEST(col1, col2, col3) AS max_value FROM table;
SELECT LEAST(col1, col2, col3) AS min_value FROM table;

一行完成,支持任意多个参数。任一参数为 NULL 则返回 NULL(与 MySQL 行为一致)。

四、新特性三:QUALIFY

背景:窗口函数的计算结果无法直接在 WHERE 子句中使用,必须通过子查询或 CTE 包装一层。QUALIFY 解决了这个痛点。

旧写法(查每个分类销售额排名前 3 的产品):

WITH ranked AS (
    SELECT 
        category,
        product,
        sales,
        ROW_NUMBER() OVER(PARTITION BY category ORDER BY sales DESC) AS rn
    FROM products
)
SELECT category, product, sales
FROM ranked
WHERE rn <= 3;

SQL:2023 新写法:

sql

SELECT 
    category,
    product,
    sales,
    ROW_NUMBER() OVER(PARTITION BY category ORDER BY sales DESC) AS rn
FROM products
QUALIFY rn <= 3;

QUALIFY 直接过滤窗口函数结果,无需额外包装层。

五、补充:SQL:2023 其他实用特性

  • 十六进制/八进制字面量:0xFF、0o755
  • 数字下划线分组:1_000_000 替代 1000000
  • ANY_VALUE() :解决 ONLY_FULL_GROUP_BY 模式下的限制
  • SQL/PGQ(图查询) :SQL 标准中首次纳入图查询能力

六、主流数据库兼容性一览

数据库 GREATEST/LEAST JSON_TABLE QUALIFY
MySQL 8.0 ✅ ❌ ❌
PostgreSQL 16+ ✅ ⚠️ 部分 ❌
Oracle 23c ✅ ✅ ❌
SQL Server 2022 ❌ ❌ ❌
Snowflake/BigQuery ✅ ✅ ✅

升级建议:GREATEST/LEAST 兼容性最好,可优先推广。JSON_TABLE 需确认数据库版本。QUALIFY 当前主要在云数仓场景可用。

七、小结

SQL:2023 新增的特性远不止这三个,但它们是最贴近日常开发、改造门槛最低的一组。

下次写 SQL 的时候,试试这些新写法——代码量减半,可读性翻倍。

小耶在手,SQL 不愁

还有什么想了解的,欢迎留言!小耶一定知无不言言无不尽……我们下次见~

相关文章
|
23天前
|
SQL 人工智能 Oracle
VLDB 2026核心议题解读:当负载被AI改写,数据库的内核该往哪走?
国际数据库顶级会议VLDB 2026将“AI Agent时代的数据系统”列为核心议题,数据库研究正在转向“如何让数据被AI Agent理解和使用”。当负载被AI改写,数据库需要重新设计什么?DBA的技能储备需要往哪个方向延伸?
|
25天前
|
SQL 监控 关系型数据库
MySQL索引合并优化器陷阱:为什么复合索引比索引合并快一个数量级?
MySQL优化器有一个“自作聪明”的行为——当单列索引无法完全覆盖查询时,它可能选择索引合并(Index Merge) ,同时使用多个单列索引,把结果集合并起来。听起来很合理对吧?但索引合并有严格的适用条件,用错了比全表扫描还慢——尤其是UNION类型的索引合并,需要对多个结果集去重和排序,代价极高。本文拆解索引合并的3种类型、3个踩坑场景,以及什么时候该用复合索引替代。
|
26天前
|
SQL 关系型数据库 MySQL
别再盯着EXPLAIN的rows列了,8.0.18之后有更好的选择
EXPLAIN是DBA最常用的工具之一,但大多数人还在看type、rows、Extra这些传统字段——然后靠经验猜。MySQL 8.0.18开始引入的EXPLAIN ANALYZE,直接把实际执行时间和行数输出给你看,不用猜了。本文对比传统EXPLAIN和EXPLAIN ANALYZE的差异,展示如何用新工具把执行计划分析这件事从“猜”变成“看”。
|
1月前
|
存储 SQL 容灾
共享存储集群 vs 分布式多副本:同城双活两条技术路线怎么选?
同城双活正在成为金融、政务等核心系统的容灾标配——RPO=0、RTO<30秒。但真正的落地远不止“两个机房各放一套数据库”那么简单。网络延迟的容忍度、脑裂预防机制、同步复制的性能代价、以及故障切换后的数据回滚,每一个环节都可能成为“最后一公里”的绊脚石。本文从容灾架构演进入手,拆解同城双活的核心技术原理、关键挑战与应对方案,并结合同城双中心方案及实测数据进行深度解析。
|
1月前
|
SQL 存储 关系型数据库
分区裁剪失效、DDL卡死、元数据爆炸:分区表的3个真实代价
很多人觉得分区表是“轻量级分库分表”——数据分开放、查询只扫一个区、过期数据直接DROP分区,听起来很完美。但分区表有严格的适用边界和隐藏代价:分区键选错导致所有查询都扫全部分区、分区数量过多导致DDL巨慢、跨分区查询比普通表还慢……本文从分区表的核心原理出发,拆解4种分区类型、3个真实踩坑场景,以及分区表与分库分表的本质区别,帮你一次性搞清楚到底该不该用。
|
1月前
|
JSON 关系型数据库 MySQL
MySQL 5.7升级到8.0之后,JSON查询的性能瓶颈真的解决了吗?
MySQL 5.7引入原生JSON类型,8.0支持多值索引,至今已近十年。但大量开发人员仍在把JSON当“万能兜底字段”——不管什么数据都往里塞,等查询慢到怀疑人生才想起来排查。本文拆解JSON字段查询的5个高频踩坑场景,给出虚拟列索引、多值索引等正确的优化方案。
|
1月前
|
SQL 运维 关系型数据库
2026年分布式数据库有哪些主流选择?先评估这5个维度再决定
分布式数据库选型,99%的文章在列表格比参数——但真正的决策关键不在厂商PPT里,在上线后的真实运维里。本文从网络延迟容忍度、SQL兼容性验证、在线扩容能力、全局索引代价、运维工具链成熟度5个维度出发,给出可落地的评估方法和决策建议,帮助你在选型阶段避开那些“只有上线后才会发现”的坑。
|
2月前
|
存储 消息中间件 SQL
Redis大Key优化完全指南:三种类型、五种拆分策略、一套渐进式方案
大key是Redis最隐蔽的性能杀手——它不会直接报错,只会让你半夜收到延迟告警、主从断开、请求超时。本文从大key的三种类型出发,拆解String、Hash、Set、ZSet、List五类数据结构的拆分策略,提供渐进式拆分的完整方案,并给出数据结构选型的“防患于未然”建议,帮助读者从“发现大key”走向“根治大key”。
|
2月前
|
存储 BI OLAP
月账单从340美元到0美元?我把SaaS分析迁到了DuckDB
从云数仓高额账单的痛点出发,讲清DuckDB嵌入式分析为什么火(列式存储+向量化执行+免ETL直查文件),划清它能替代谁、替代不了谁,结合行业降本案例给出适用边界判断与避坑清单。
|
12天前
|
存储 监控 关系型数据库
为什么UUID做主键写入慢?InnoDB页分裂的触发机制与实测数据
InnoDB以16KB的页为单位管理数据,但很多人只知道“页分裂会降低性能”,不清楚页分裂在什么条件下触发、页合并何时发生、填充因子如何影响空间利用率。本文从数据页的物理结构出发,拆解页分裂与页合并的触发机制、顺序插入与随机插入的性能差异、填充因子的作用与调优策略,帮你理解InnoDB存储引擎最底层的运行逻辑。