SQL 模式

sql_mode 是 MatrixOne 中的一个系统参数,用于指定 MatrixOne 执行查询和操作的模式。sql_mode 可以影响 MatrixOne 的语法和语义规则,从而改变 MatrixOne 查询 SQL 的行为。在本篇文章中,将为你介绍 sql_mode 的模式、作用以及如何设置 SQL 模式。

MatrixOne 接受多个兼容 MySQL 的 SQL 模式名称,但只有经过验证的部分模式会改变解析或执行行为。不能因为某个 token 可被设置,就认为它已经完整实现了 MySQL 的全部语义。

已生效的模式行为

模式

MatrixOne 行为

ANSI_QUOTES

将双引号中的 token 解析为标识符,而不是字符串字面量。

PIPES_AS_CONCAT

将 `

STRICT_TRANS_TABLES / STRICT_ALL_TABLES

在已支持的 DML 和 DDL 路径中启用严格赋值和转换检查,包括宽度、数值和时间转换;并非所有数据类型的覆盖范围都与 MySQL 完全相同。

NO_ZERO_DATE

只有与 STRICT_TRANS_TABLESSTRICT_ALL_TABLES 组合时,才会改变零日期/零时间值的写入行为。仅启用 NO_ZERO_DATE,或仅启用 strict mode,都不会产生这一组合拒绝行为。

ERROR_FOR_DIVISION_BY_ZERO

与严格模式一起使用时,非 IGNOREINSERT/UPDATE 中除零会报错。普通 SELECT 仍返回 NULLINSERT IGNORE/UPDATE IGNORE 不会触发该错误。

ONLY_FULL_GROUP_BY

未启用 MATRIXONE_NATIVE 时保留 MySQL 兼容例外:列被 WHERE 限定为单一值,或列函数依赖于已分组主键时,可以不显式写入 GROUP BY。同时启用 ONLY_FULL_GROUP_BY,MATRIXONE_NATIVE 时采用更严格的字面规则,拒绝未显式列入 GROUP BY 的非聚合列。未启用 ONLY_FULL_GROUP_BY 时,裸列使用兼容 MySQL 的 ANY_VALUE 处理。

MATRIXONE_NATIVE

启用下文说明的 MatrixOne 特有行为。

其他可接受的模式名称也可以写入 sql_mode,但除非有单独文档和验证,否则不保证完整实现 MySQL 对应行为。

MATRIXONE_NATIVE

MATRIXONE_NATIVE 是 MatrixOne 特有的兼容模式。目前至少会改变以下行为:

  • 允许 MySQL 拒绝的 MatrixOne 原生 DML 写法,例如在 UPDATE 赋值中使用窗口函数;它不会使窗口函数在逐行计算的 CHECK 约束中变为合法。

  • 字符串转数值时必须消费完整的有效 token,不再接受只有前缀为数值的字符串。有效 token 仍可使用 MatrixOne 的 0x0b0o 等数值扩展。

设置 sql_mode 会替换完整的模式列表。例如,SET SESSION sql_mode = 'MATRIXONE_NATIVE' 同时移除了默认的 ONLY_FULL_GROUP_BY,因此会采用宽松的分组规则。同时包含两个模式时启用 MatrixOne 更严格的分组规则,不再应用未启用 MATRIXONE_NATIVE 时的函数依赖和 WHERE 单值例外。

SET sql_mode = CONCAT(@@sql_mode, ',MATRIXONE_NATIVE');

查看 sql_mode

在 MatrixOne 中使用以下命令查看 sql_mode:

SELECT @@global.sql_mode;--全局模式
SELECT @@session.sql_mode;--会话模式

设置 sql_mode

在 MatrixOne 中使用以下命令设置 sql_mode:

-- 全局模式,新建连接后生效。
SET GLOBAL sql_mode = 'xxx';
-- 当前会话生效。
SET SESSION sql_mode = 'xxx';

示例

DROP DATABASE IF EXISTS sql_mode_demo;
CREATE DATABASE sql_mode_demo;
USE sql_mode_demo;

CREATE TABLE student (
    id INT,
    name CHAR(20),
    age INT,
    nation CHAR(20)
);

INSERT INTO student VALUES (1,'tom',18,'上海'),(2,'jan',19,'上海'),(3,'jen',20,'北京'),(4,'bob',20,'北京'),(5,'tim',20,'广州');

-- 在 ONLY_FULL_GROUP_BY 模式下执行会报错。
-- Expected-Success: false
SELECT * FROM student GROUP BY nation;

SET session sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_TRANS_TABLES';

-- 关闭当前会话的 ONLY_FULL_GROUP_BY 模式后,同一查询执行成功。
SELECT * FROM student GROUP BY nation;

DROP DATABASE sql_mode_demo;