最新标准SQL:2023新特性预览

介绍了即将发布的SQL:2023标准中的新特性,包括增强的SQL语言功能、新增的JSON支持以及属性图查询语言。这些更新将提高数据库系统的灵活性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQL 标准每隔几年就会发布一次,最新的 SQL:2023 已经编写完成,预计很快就会发布。

本文给大家简单介绍一下最新标准中的型特性,主要分为以下三大类别:

  1. 已有 SQL 语言的增强;
  2. JSON 相关的新特性;
  3. 新增的属性图查询语言。

该版本新增功能都属于可选特性。

SQL 增强

UNIQUE 约束中的空值(F292)

这个功能用于定义唯一约束中是否允许多个空值。例如:

CREATE TABLE t1 (
    a int,
    b int,
    c int,
    UNIQUE (a, b, c)
);

INSERT INTO t1 VALUES (1, NULL, NULL);
INSERT INTO t1 VALUES (1, NULL, NULL);  -- ?

问题在于第二个插入语句是否会违法唯一约束。

显然,已有的标准没有明确的定义。为了解决这个问题,新标准增加了一个选项。例如:

CREATE TABLE t2 (
    a int,
    b int,
    c int,
    UNIQUE NULLS DISTINCT (a, b, c)
);

INSERT INTO t2 VALUES (1, NULL, NULL);
INSERT INTO t2 VALUES (1, NULL, NULL);  -- 正确

同时,

CREATE TABLE t3 (
    a int,
    b int,
    c int,
    UNIQUE NULLS NOT DISTINCT (a, b, c)
);

INSERT INTO t3 VALUES (1, NULL, NULL);
INSERT INTO t3 VALUES (1, NULL, NULL);  -- 错误

NULLS DISTINCT 选项将多个空值看作不同的数据,因此不会违反唯一约束;NULLS NOT DISTINCT 选项将多个空值看作相同的数据,因此违反了唯一约束。

该选项的默认值取决于数据库产品的具体实现,这样可以兼容已有的行为。

分组表中的 ORDER BY(F868)

我们来看一个示例:

CREATE TABLE product (
    product_id int PRIMARY KEY,
    product_name varchar,
    product_code varchar UNIQUE
);

CREATE TABLE product_part (
    product_id int,
    part_id int,
    num int,
    PRIMARY KEY (product_id, part_id)
);

SELECT product.product_id, sum(product_part.num)
FROM product JOIN product_part ON product.product_id = product_part.product_id
GROUP BY product.product_id
ORDER BY product.product_code;

以上示例在大多数 SQL 实现中都能正常工作,但是标准却不允许这种查询方式。也就是说,SQL 标准不允许使用没有出现在 SELECT 列表中的分组表字段(product.product_code)进行排序。新标准则允许 SQL 实现明确支持这种行为。

作为用户,我们并不需要关心这个问题。

GREATEST 和 LEAST 函数(T054)

这个功能增加了两个新的标量函数:GREATEST(最大值)以及 LEAST(最小值)。它们不是聚合函数 MAX 和 MIN,而是返回一组参数中的最大值和最小值。实际上很多数据库已经实现了这两个函数:

SELECT greatest(1, 2);  --> 2
SELECT least(1, 2);     --> 1

SELECT greatest(1, 2, 3);  --> 3
SELECT least(1, 2, 3);     --> 1

字符串填充函数(T055)

这个功能增加了两个新的字符串函数:LPAD(左侧填充)以及 RPAD(右侧填充)。这两个函数同样在很多数据库中已经有了实现:

SELECT lpad(cast(12345.67 as varchar), 12, '*');

****12345.67

默认使用的填充字符为空格。

多字符 TRIM 函数(T056)

已有的单字符截断函数(TRIM({LEADING|TRAILING|BOTH} ‘x’ FROM val))只能指定要截断的单个字符,新函数则可以指定多个需要截断的字符,而且语法更加简洁。例如:

SELECT ltrim('****12345.67', '*');

可选的字符串类型最大长度(T081)

这个功能允许不指定 VARCHAR 类型的最大长度。在此之前,我们经常会看到为了支持任意长度而指定一个很大的长度值:

CREATE TABLE t1 (
    a VARCHAR(1000),
    b VARCHAR(4000),
	...
);

现在可以简单的指定数据类型:

CREATE TABLE t1 (
    a VARCHAR,
    b VARCHAR,
	...
);

这种情况下,字段的最大长度取决于数据库实现。

增强的递归循环标识(T133)

CYCLE 子句是鲜为人知的一个递归查询功能,可以用于检测循环递归:

WITH RECURSIVE ... (
    SELECT ...
      UNION ALL
    SELECT ...
)
CYCLE id SET is_cycle TO 'Y' DEFAULT 'N' USING path;

这种方式可以基于 id 字段检测是否出现循环递归,并且将 is_cycle 字段设置为指定值。

当 SQL 标准增加递归循环时,还没有布尔类型,因此使用了一个字符串。如今 SQL 标准提供了布尔类型,因此上面的查询可以改进为:

WITH RECURSIVE ... (
    SELECT ...
      UNION ALL
    SELECT ...
)
CYCLE id SET is_cycle USING path;

ANY_VALUE 函数(T626)

这个新的聚合函数可以从一组数据中返回任意一个非空值。例如:

CREATE TABLE t1 (
    a int,
    b int
);

INSERT INTO t1 VALUES (1, 11), (1, 22), (1, 33);

SELECT a, any_value(b) 
FROM t1 
GROUP BY a;

以上查询可能会返回(1 | 11)、(1 | 22)或者(1 | 33)。

非十进制的整数常量(T661)

这个新功能支持十六进制、八进制以及二进制的整数常量。

SELECT 0xFFFF, 0o755, 0b11001111;

数字常量中的下划线(T662)

这个功能允许在数字常量中使用下划线,提高可读性。

SELECT ... WHERE a > 1_000_000;
UPDATE ... SET x = 0x_FFFF_FFFF ...

JSON 新功能

JSON 数据类型(T801)

新标准增加了 JSON 数据类型。许多数据库产品实际上已经提供了这个类型。

SQL:2016 只是支持了 JSON 数据的操作,数据仍然使用字符串存储。新的功能同时还增加了一些 JSON 相关的函数,例如 JSON_SERIALIZE、JSON_SCALAR 以及 IS JSON。

增强的 JSON 数据类型(T802)

这个功能可以为 JSON 类型指定额外的选项。具体来说,可以指定一个唯一键检测,例如 JSON(‘…text…’ WITH UNIQUE KEYS)。

基于字符串的 JSON(T803)

这个功能代表了 SQL:2016 中的字符串 JSON。数据库提供的 JSON 函数(例如 JSON_OBJECT、JSON_OBJECTAGG、JSON_TABLE 等)可以选择支持字符串格式的 JSON 数据还是原生的 JSON 数据类型,也可以支持两者。

SQL/JSON 路径中的十六进制整数常量(T840)

这个功能允许在 SQL/JSON 路径语言中使用十六进制整数常量。

虽然不属于这个功能,但是 SQL 标准现在允许以扩展插件的形式支持 JavaScript(ECMAScript),因此不需要每次 ECMAScript 更新时更新 SQL 标准。所以 SQL/JSON 路径现在也可以支持最新 ECMAScript 中的其他数字常量,例如二进制整数和下划线分隔符。

SQL/JSON 简化访问符(T860-T864)

“简化访问符”功能允许使用点号和数组语法访问 JSON 数据中的复合类型和数组类型。例如,假设字段 j 是一个 JSON 类型,包含以下数据:

{"foo": {"bar": [100, 200, 300]}, ...}

我们可以使用简化访问符获取字段中的信息:

SELECT t.j.foo.bar[2], ... 
FROM tbl t ...

SQL/JSON 元素方法(T865-T878)

SQL/JSON 元素方法或者函数可以在 SQL/JSON 路径表达式中使用,对元素值进行处理。SQL:2016 已经定义了一些这类方法,例如 abs()、floor()、size()。新增的方法主要用于数据类型转换:

  • T865: SQL/JSON item method: bigint()
  • T866: SQL/JSON item method: boolean()
  • T867: SQL/JSON item method: date()
  • T868: SQL/JSON item method: decimal()
  • T869: SQL/JSON item method: decimal() with precision and scale
  • T870: SQL/JSON item method: integer()
  • T871: SQL/JSON item method: number()
  • T872: SQL/JSON item method: string()
  • T873: SQL/JSON item method: time()
  • T874: SQL/JSON item method: time_tz()
  • T875: SQL/JSON item method: time precision
  • T876: SQL/JSON item method: timestamp()
  • T877: SQL/JSON item method: timestamp_tz()
  • T878: SQL/JSON item method: timestamp precision

JSON 数据比较功能(T879-T882)

这个功能允许针对 JSON 数据类型的比较、排序以及分组操作。

属性图查询语言

这是 SQL 标准中增加的一个全新部分:Property Graph Queries (SQL/PGQ)。这个新功能支持使用图数据库的方式查询表中的数据。

完整的属性图查询语言比较复杂,以下是一个简单的示例:

CREATE TABLE person (...);
CREATE TABLE company (...);
CREATE TABLE ownerof (...);
CREATE TABLE transaction (...);
CREATE TABLE account (...);

CREATE PROPERTY GRAPH financial_transactions
    VERTEX TABLES (person, company, account)
    EDGE TABLES (ownerof, transaction);

SELECT owner_name,
       SUM(amount) AS total_transacted
FROM financial_transactions GRAPH_TABLE (
  MATCH (p:person WHERE p.name = 'Alice')
        -[:ownerof]-> (:account)
        -[t:transaction]- (:account)
        <-[:ownerof]- (owner:person|company)
  COLUMNS (owner.name AS owner_name, t.amount AS amount)
) AS ft
GROUP BY owner_name;

以上示例中,表之间还需要定义外键,这样属性图定义才能确定它们之间的联系;或者也可以在属性图定义时指定表之间的联系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不剪发的Tony老师

为 5 个 C 币而折腰。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值