运行时名称: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`。 - 双引号:列名存在时按标识符;不存在时当字符串字面量。
- 分页两种写法都可用:
SELECT id FROM t LIMIT 0, 5;
SELECT id FROM t LIMIT 5 OFFSET 0;
ORDER BY可用列名或序号;GROUP BY/HAVING/DISTINCT/UNION/INTERSECT/EXCEPT可用。- CTE:
WITH x AS (…);递归用WITH RECURSIVE r (n) AS (SELECT 1 UNION ALL SELECT n + 1 FROM r WHERE n < 3)(实测返回 1、2、3)。 SELECT 1 AS x(无FROM)可用。NOW()/UPPER()/IFNULL()等共享函数可用。
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)
);
AUTO_INCREMENT列必须显式写NOT NULL,否则报列 'id' 声明为 NULL,不能做主键;请改成 NOT NULL(原生 MySQL 允许省略)。- 行内
UNIQUE KEY/UNIQUE生效;普通KEY/INDEX子句被接受但不建索引。 CHECK真校验;普通列默认可空;外键不接受。
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;
INSERT … VALUES只接受字面量:VALUES (2, UPPER('b'), 2)报期望字面量,实际遇到 'UPPER'。INSERT … SELECT不支持:期望关键字 'VALUES',实际遇到 'SELECT'。INSERT … SET不支持:期望关键字 'VALUES',实际遇到 'SET'。- 多表
UPDATE t, u SET …不支持:期望关键字 'SET',实际遇到 'Comma'。 INSERT IGNORE/REPLACE/ON DUPLICATE KEY UPDATE可用,但语义有偏差(见 3.3)。
2.6 存储过程
CREATE PROCEDURE pnum (IN n INT)
BEGIN
INSERT INTO u (k) VALUES (n);
END;
CALL pnum(7);
- 过程体支持
DECLARE/SET/IF/WHILE/END WHILE,参数可用。 - 循环有 10 000 次上限:超过报
WHILE 循环超过 10000 次,可能是死循环。 - 已知缺陷:过程体里的字符串字面量会被当成列名:
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 行
- 实现为
DELETE并重置自增:清空后下一行id从 1 开始(实测)。 - 返回文案是
DELETE n 行,不是 MySQL 的Query OK。
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 的回显形状
SHOW COLUMNS:TEXT显示为VARCHAR(255),BOOL显示为TINYINT(1),DECIMAL(10,2)保留精度,自增列Extra为auto_increment,UNSIGNED不显示。VARCHAR(n)的长度不回显(统一VARCHAR(255)),且不参与校验:VARCHAR(5)可存abcdefgh。SHOW CREATE TABLE:固定尾部ENGINE=InnoDB DEFAULT CHARSET=utf8mb4,列类型同样按上表回显。SHOW CREATE TABLE只回显主键,不输出UNIQUE KEY/ 普通KEY(实测:带UNIQUE KEY uk (k)的mu表,回显里只有PRIMARY KEY)。不能拿它当结构真值做迁移比对。SHOW CREATE TABLE nope(表不存在)返回空骨架,不报错:
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. 迁移建议
- 依赖大小写不敏感的查询,显式
LOWER()两侧(本引擎区分大小写)。 INSERT … SELECT、INSERT … SET、多表UPDATE拆开写;INSERT值里的函数先在应用层算好。INSERT IGNORE/REPLACE/ON DUPLICATE KEY UPDATE只按主键判重;有唯一键时先查再写。AUTO_INCREMENT主键补NOT NULL。- 过程体里的字符串字面量暂时不要用(已知缺陷),把字符串放到参数里传。
CREATE TRIGGER迁移到 T-SQL 方言或用应用层替代;索引只保留主键/唯一约束。VARCHAR(n)、DECIMAL之外的类型约束在应用层再校验;DECIMAL(p,s)在本引擎是生效的。SHOW CREATE TABLE不能当结构真值(引擎/字符集/长度是固定回显,且不输出UNIQUE KEY等约束)。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。