/ 三方言语法手册 / MySQL
DbSql · 文档

MySQL 方言

每条支持 / 不支持 / 与厂商数据库的差异,都由 verify.sh 在真实二进制上跑过。

运行时名称:MySQL;CLI --dialect mysql;需要 libdbsql_mysql_plugin.so。 先读 总览 了解方言隔离、事务模型和共享函数表。

1. 调用方式

cd /path/to/dbsql
./target/release/dbsql --root /data --dialect mysql sql mydb "SELECT * FROM t LIMIT 0, 5"

插件探测顺序:plugins/libdbsql_mysql_plugin.so → plugins/dbsql_mysql_plugin.so → 当前目录;也可 --plugin <路径>(写在子命令前)。

2. 支持的语法

2.1 查询

SELECT id FROM t LIMIT 0, 5;
SELECT id FROM t LIMIT 5 OFFSET 0;

2.2 DDL

语句 说明
CREATE DATABASE / SCHEMA,DROP DATABASE / SCHEMA —
CREATE TABLE … ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 子句被接受并忽略(存储引擎固定)
DROP TABLE [IF EXISTS] 存在的表正常删除
CREATE VIEW … AS SELECT … / DROP VIEW 不支持 CREATE OR REPLACE VIEW
CREATE PROCEDURE/FUNCTION … BEGIN … END / DROP … [IF EXISTS] 见 2.6
ALTER TABLE … ADD [COLUMN] … / MODIFY … / CHANGE … / RENAME … / DROP [COLUMN] … 一次只允许一个子句
TRUNCATE [TABLE] t 等价 DELETE + 重置自增(见 3.2)
USE <库> 空操作(当前库由 CLI/请求参数决定)
SHOW DATABASES / SHOW SCHEMAS 列出所有库
SHOW TABLES [LIKE '模式'] —
SHOW COLUMNS / FIELDS FROM t [LIKE '模式'] 见 3.5 的类型回显
SHOW CREATE TABLE t 固定输出 ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

不支持:CREATE/DROP INDEX、ALTER TABLE … ADD/DROP INDEX、CREATE TRIGGER、CREATE OR REPLACE VIEW。

2.3 类型映射

map_type(crates/dbsql-sql-mysql/src/lib.rs):

写法 引擎类型
TINYINT [UNSIGNED] / BIT byte
SMALLINT / YEAR short
MEDIUMINT / INT / INTEGER int
BIGINT long
FLOAT float
DOUBLE / REAL / DOUBLE PRECISION double
DECIMAL / NUMERIC / FIXED decimal((p,s) 会校验小数位)
VARCHAR / NVARCHAR / TEXT / TINYTEXT / MEDIUMTEXT / LONGTEXT string
CHAR / NCHAR char(单字符类型)
DATE dateonly
DATETIME / TIMESTAMP datetime
JSON json
ENUM / SET string
BLOB / TINYBLOB / MEDIUMBLOB / LONGBLOB / BINARY / VARBINARY blob
BOOL / BOOLEAN bool
原生 STRING / INT32 / BYTE / GUID / DATEONLY 原样

UNSIGNED / ZEROFILL 被跳过(不改变值域);未知类型报 不支持的 MySQL 类型 '…'。

2.4 约束与自增

CREATE TABLE u (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  k INT,
  UNIQUE KEY uk (k)
);

2.5 写入

INSERT INTO t (id, v) VALUES (1, 'a');
INSERT INTO t (id, v) VALUES (1, 'a'), (2, 'b');   -- 多行可用
UPDATE t SET n = n + 1 WHERE id = 1;               -- UPDATE 右侧可用表达式
DELETE FROM t WHERE id = 1;

2.6 存储过程

CREATE PROCEDURE pnum (IN n INT)
BEGIN
    INSERT INTO u (k) VALUES (n);
END;

CALL pnum(7);
CREATE PROCEDURE pstr () BEGIN INSERT INTO t (v) VALUES ('x'); END;
CALL pstr();
-- 错误:列 'v' 的值写错了:表中不存在列 'x'。可用列:

CREATE PROCEDURE psel () BEGIN SELECT 'x' AS s; END;
CALL psel();
-- 错误:无法计算表达式:x AS s

纯数字/参数的过程体正常(CALL pnum(7) 实测插入 7)。

2.7 事务

BEGIN / COMMIT / ROLLBACK 只允许平台管理员;进程级单事务,CLI 跨命令即丢失,见 总览第 7 节。

3. 与 MySQL 有差异的地方

3.1 标识符与大小写

主题 本引擎 MySQL 8 默认
字符串比较 / LIKE 区分大小写:v = 'ABCDEFGH' 匹配不到 abcdefgh utf8mb4_0900_ai_ci 不区分
反引号 支持 支持
双引号 有同名列时当标识符,否则当字符串 默认当字符串(ANSI_QUOTES 关闭时)

3.2 TRUNCATE

$ ... sql mdb "TRUNCATE TABLE u"
DELETE 1 行

3.3 冲突处理只认主键

INSERT IGNORE、REPLACE、ON DUPLICATE KEY UPDATE 只探测主键:

INSERT IGNORE INTO u (k) VALUES (9);   -- 与 UNIQUE KEY uk 冲突
错误:唯一约束 'uk' 冲突:列 (k) 的值 ('9') 与已存在的行重复

REPLACE INTO mu2 (id, k) VALUES (2, 5);  -- 与 UNIQUE KEY uk 冲突
错误:唯一约束 'uk' 冲突:列 (k) 的值 ('5') 与已存在的行重复

INSERT INTO u (k) VALUES (9) ON DUPLICATE KEY UPDATE k = 10;  -- 同上
错误:唯一约束 'uk' 冲突:列 (k) 的值 ('9') 与已存在的行重复

三条语句命中唯一键时都直接报错,只有主键冲突才进入 IGNORE / REPLACE / UPDATE 分支。

主键冲突时语义正常:INSERT IGNORE 跳过、REPLACE 覆盖、ON DUPLICATE KEY UPDATE 更新(实测 id=1 的 k 被改为 11,REPLACE 后改为 12)。

3.4 默认值与生成列

写法 表现
DEFAULT <字面量> 可用
DEFAULT CURRENT_TIMESTAMP 列 'ts':默认值 'CURRENT_TIMESTAMP' 要按写入时刻求值,尚未支持;请改写字面量
DEFAULT UPPER('a') DEFAULT 后面要写字面量或 CURRENT_TIMESTAMP,这里是 'UPPER'
GENERATED ALWAYS AS (…) 暂不支持生成列(GENERATED ALWAYS AS ...),请改用触发器或应用层计算
ON UPDATE CURRENT_TIMESTAMP 解析失败:期望 ')',实际遇到 'ON'

3.5 SHOW 的回显形状

nope	CREATE TABLE `nope` (

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.6 其他语义差异

主题 本引擎 MySQL
AUTO_INCREMENT 必须显式 NOT NULL 可省略
INSERT … VALUES 只接受字面量 接受表达式/函数
INSERT … SELECT 不支持 支持
多表 UPDATE 不支持 支持
INSERT … SET 不支持 支持
CROSS JOIN 不支持(SELECT 语句末尾存在多余内容) 支持
UPDATE 多子句 ALTER 一次一个子句 支持多子句
CREATE/DROP INDEX 不支持 支持
CREATE TRIGGER 不支持 支持
GROUP_CONCAT / DATE_FORMAT / IF() 未定义的函数 支持
用户变量 SELECT @v 原样返回字符串 @v,不报错 返回变量值,未定义时为 NULL
顶层 SET / @@version 不支持 支持
USE 空操作 切换当前库
DROP TABLE IF EXISTS(表不存在) 返回一行 COUNT(*) 0(异常形状) 成功、无输出
TRUNCATE 自增 重置为 1 重置为 1(一致)
NULL 排序 ASC NULL 在前 一致
列默认可空性 默认可空 一致
CHAR(n) 单字符类型 定长 n
VARCHAR(n) 不校验 严格
字符串大小写 区分 默认不区分

4. 不支持的功能

功能 实测报错 替代
CREATE TRIGGER CREATE 后不支持的对象类型(位于 7) 在 T-SQL 方言建触发器 / 应用层处理
CREATE INDEX / DROP INDEX CREATE/DROP 后不支持的对象类型 建表时写 UNIQUE / 主键
ALTER TABLE … ADD/DROP INDEX ALTER TABLE 暂不支持 ADD INDEX(只支持 ADD [COLUMN]) 同上
CREATE OR REPLACE VIEW CREATE 后不支持的对象类型(位于 7) DROP VIEW + CREATE VIEW
多子句 ALTER TABLE ALTER TABLE 一次只支持一个子句(逗号分隔的多子句暂不支持) 拆成多条
INSERT … SELECT / INSERT … SET / 多表 UPDATE 见 2.5 拆成单表语句
表达式默认值 / 生成列 / ON UPDATE CURRENT_TIMESTAMP 见 3.4 应用层计算
SET / @@version / 用户变量 不支持(SELECT @v 静默返回字符串) 参数化请求
ROW_NUMBER() OVER (…) 语句结束后存在多余内容:'LParen' 应用层编号
CROSS JOIN SELECT 语句末尾存在多余内容 逗号连接
外键 见 总览第 5 节 NOT NULL + 应用层校验
已删除表上的 SHOW CREATE TABLE 返回空骨架(不报错) 先 SHOW TABLES 确认

5. 迁移建议

  1. 依赖大小写不敏感的查询,显式 LOWER() 两侧(本引擎区分大小写)。
  2. INSERT … SELECT、INSERT … SET、多表 UPDATE 拆开写;INSERT 值里的函数先在应用层算好。
  3. INSERT IGNORE / REPLACE / ON DUPLICATE KEY UPDATE 只按主键判重;有唯一键时先查再写。
  4. AUTO_INCREMENT 主键补 NOT NULL。
  5. 过程体里的字符串字面量暂时不要用(已知缺陷),把字符串放到参数里传。
  6. CREATE TRIGGER 迁移到 T-SQL 方言或用应用层替代;索引只保留主键/唯一约束。
  7. VARCHAR(n)、DECIMAL 之外的类型约束在应用层再校验;DECIMAL(p,s) 在本引擎是生效的。
  8. SHOW CREATE TABLE 不能当结构真值(引擎/字符集/长度是固定回显,且不输出 UNIQUE KEY 等约束)。
  9. SHOW CREATE TABLE 丢 UNIQUE KEY 意味着「靠回显重建表」会静默丢掉唯一约束;迁移时以原库 DDL 为准。

6. 复现

cd /path/to/dbsql
./target/release/dbsql --root /tmp/dbsql-dialect-verify create database mdb
./target/release/dbsql --root /tmp/dbsql-dialect-verify --dialect mysql sql mdb \
  "CREATE TABLE t (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, v VARCHAR(5))"
./target/release/dbsql --root /tmp/dbsql-dialect-verify --dialect mysql sql mdb \
  "INSERT INTO t (v) VALUES ('abcdefgh')"
# INSERT 1 行(长度不校验)

./target/release/dbsql --root /tmp/dbsql-dialect-verify --dialect mysql sql mdb \
  "CREATE TRIGGER trg AFTER INSERT ON t AS INSERT INTO t (v) VALUES ('x')"
# 错误:CREATE 后不支持的对象类型(位于 7)

完整清单:verify.sh。