/ 三方言语法手册 / T-SQL
DbSql · 文档

T-SQL 方言

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

运行时名称:T-SQL;CLI --dialect standard(默认),旧值 mssql 仍兼容;不需要插件。 先读 总览 了解方言隔离、事务模型和共享函数表。

1. 调用方式

dbsql --root /data sql mydb "SELECT TOP 5 id, name FROM users ORDER BY id"

T-SQL 是 CLI 的默认方言,可省略 --dialect。HTTP 侧 /api/sql、/api/select 的 "dialect" 留空或写 standard/mssql 都走这里。

2. 支持的语法

2.1 DDL

语句 说明
CREATE DATABASE <库> 与方言无关的库级操作
CREATE TABLE <表> (<列> <类型> [约束], …, [表级约束]) 见 2.2 / 2.3
DROP TABLE <表> —
CREATE VIEW <视图> AS SELECT … / DROP VIEW <视图> 不支持 CREATE OR REPLACE VIEW
CREATE PROCEDURE <名> () AS BEGIN … END / DROP PROCEDURE <名> 见 2.6
CREATE FUNCTION … / DROP FUNCTION … 与过程同一套过程体解释器
CREATE TRIGGER … / DROP TRIGGER … 见 2.7
CREATE INDEX <索引> ON <表> (<列>, …) 不存在 CREATE UNIQUE INDEX
ALTER TABLE <表> ADD <列定义> / MODIFY <列定义> / RENAME … 一次只能一个子句,逗号分隔的多子句会被拒
SELECT … INTO <新表> FROM … 建表并落数据;语句本身返回 0 行

2.2 类型映射

解析器把 SQL Server 常见类型名归一成引擎类型(crates/dbsql-sql/src/parser.rs 的 map_std_type):

写法 引擎类型 备注
NUMBER / NUMERIC / DECIMAL / DEC / MONEY / SMALLMONEY decimal DECIMAL(p,s) 会校验小数位;超位直接报错,不四舍五入
VARCHAR / NVARCHAR / VARCHAR2 / NVARCHAR2 / NTEXT / CLOB / NCLOB / TEXT / STRING / XML / SYSNAME string (n) 只解析、不校验长度
CHAR / NCHAR / CHAR2 char 单字符类型,不是定长 n 字符串
DATE / TIMESTAMP / DATETIME / DATETIME2 / SMALLDATETIME datetime 读回形如 2026-01-02 00:00:00
BOOLEAN / BOOL / BIT bool —
INT / INTEGER / INT32 / INT64 int —
BIGINT / LONG long —
SMALLINT / INT16 short —
TINYINT / BYTE byte 注意 SQL Server 的 TINYINT 是 0–255 无符号,这里是有符号字节
REAL / FLOAT float 单精度
DOUBLE / BINARY_DOUBLE double —
GUID / UNIQUEIDENTIFIER guid —
DATEONLY dateonly —
JSON json 写入时校验 JSON 语法
BLOB / BINARY / VARBINARY / IMAGE blob 值用 0x… 十六进制字面量

引擎原生名(byte/bool/guid/string/int/long/datetime/dateonly/float/decimal/char/short/double/json/blob)也可直接写。

反直觉点:DDL 里的 FLOAT 落单精度;但 CONVERT(FLOAT, x) 落双精度(与 SQL Server 的 float(53) 对齐)。要单精度请用 REAL。

2.3 约束

2.4 查询

SELECT TOP 2 id FROM t ORDER BY id;
SELECT id FROM t ORDER BY id OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY;
SELECT id FROM t ORDER BY id LIMIT 2 OFFSET 0;   -- 兼容写法

2.5 字面量与标识符

写法 行为
'text' / N'中文' 字符串字面量;N 前缀可用
[名字] 标识符(方括号转义)
"名字" 字符串字面量,不是标识符:SELECT "id" FROM t 每行返回 id
'a' + 'b' 文本拼接(ab)
CONVERT(INT, '12') 支持;目标类型见 map_convert_type
CAST(x AS 类型) 支持
GETDATE() / SYSDATE / CURRENT_TIMESTAMP 支持

2.6 存储过程与流程控制

CREATE PROCEDURE pc ()
AS
BEGIN
    DECLARE @i INT;
    DECLARE cur CURSOR FOR SELECT id FROM src;
    OPEN cur;
    FETCH NEXT FROM cur INTO @i;
    CLOSE cur;
    DEALLOCATE cur;
    INSERT INTO t (id, v) VALUES (100, 'p');
END

2.7 触发器

CREATE TRIGGER trg_bi BEFORE INSERT ON t
AS RAISE '不允许插入';

CREATE TRIGGER trg_ai AFTER INSERT ON t
AS INSERT INTO audit (v) VALUES (NEW.v);
-- 可跟多条语句:INSERT …; INSERT …;

DROP TRIGGER trg_ai;

2.8 SET 选项

只有下列选项会被接受;除 IDENTITY_INSERT 外都是校验后空操作:

SET NOCOUNT ON|OFF
SET ANSI_NULLS ON|OFF
SET ANSI_PADDING ON|OFF
SET ANSI_WARNINGS ON|OFF
SET ARITHABORT ON|OFF
SET CONCAT_NULL_YIELDS_NULL ON|OFF
SET NUMERIC_ROUNDABORT ON|OFF
SET IDENTITY_INSERT <表> ON|OFF      -- 空操作

SET QUOTED_IDENTIFIER 明确拒绝:

错误:SET QUOTED_IDENTIFIER 暂不支持:本引擎不能按会话切换双引号的解释口径。请删掉这一行,脚本里的字符串统一用单引号

2.9 自增列

CREATE TABLE idt (id INT IDENTITY PRIMARY KEY, v VARCHAR(5));
INSERT INTO idt (v) VALUES ('a');   -- id 自动为 1

隐式列清单会剔除自增列;显式给自增列赋值会因列数/顺序不匹配报错。

2.10 事务

BEGIN [TRANSACTION] / COMMIT / ROLLBACK 只允许平台管理员;事务是进程级单事务,CLI 每条命令一个进程,见 总览第 7 节。

3. 不支持的功能

功能 实测报错 / 表现 替代
CROSS JOIN SELECT 语句末尾存在多余内容(位于 31) 逗号连接或 INNER JOIN … ON 1=1
TOP n PERCENT TOP n PERCENT 不支持,请改写为 LIMIT(位于 14) ORDER BY … LIMIT 百分比行数
dbo. / 跨库前缀 表名 'dbo' 带库/架构前缀,dbsql 不支持跨库引用(请改写为同库表名) 同库裸表名
TRUNCATE TABLE 不支持的 SQL 语句类型:TRUNCATE DELETE FROM t
CREATE UNIQUE INDEX CREATE 后必须是 DATABASE / TABLE / INDEX / VIEW / PROCEDURE / FUNCTION / TRIGGER / SCHEDULE 建表时写 UNIQUE 约束
DROP INDEX 不支持 重建表 / 不建该索引
CREATE OR REPLACE VIEW 不支持 DROP VIEW + CREATE VIEW
DROP TABLE IF EXISTS 不支持 先查存在性再删
MERGE 不支持 UPDATE + INSERT 分两步
ISNULL(a, b) 未定义的函数 'ISNULL' COALESCE(a, b)
SET QUOTED_IDENTIFIER 见 2.8 字符串统一用单引号
窗口 PARTITION BY ROW_NUMBER 的 PARTITION BY 暂不支持 分组后分别编号 / 应用层处理
顶层 EXEC p 不支持的 SQL 语句类型:EXEC CALL p()
一条命令多条语句 SELECT 语句末尾存在多余内容 一次一条
外键 见 总览第 5 节 NOT NULL + 应用层校验

4. 与 SQL Server 有差异的地方

主题 本引擎(T-SQL 方言) SQL Server
列默认可空性 默认 NOT NULL:CREATE TABLE t (id INT PRIMARY KEY, v VARCHAR(5)) 后,INSERT INTO t (id) VALUES (1) 报 列 'v' 不允许为空(未提供值且无默认值),显式写 NULL 同样被拒;要空值必须建表时声明 NULL 默认 NULL
CHAR(n) 单字符类型;CHAR(3) 插入 'abcd' 报 列 'ch' 为字符列,字面量必须是单个字符,如 'a' 定长 n,短补空格、长截断
VARCHAR(n) / NVARCHAR(n) 只解析不校验,VARCHAR(5) 可存 abcdefgh 超长报错或截断
DECIMAL(p,s) 超小数位 报错:小数位 3 超过声明小数位 2,不四舍五入 按 s 四舍五入
双引号 字符串字面量(SELECT "id" 返回 id),且不能开 QUOTED_IDENTIFIER QUOTED_IDENTIFIER ON 时是标识符
TINYINT 有符号单字节 0–255 无符号
FLOAT DDL 落单精度;CONVERT(FLOAT, …) 落双精度 默认 float(53)(双精度)
字符串比较 / LIKE 区分大小写 取决于排序规则(安装默认多不区分)
PRINT 求值后丢弃,不输出到客户端 输出到消息流
事务作用域 进程级单事务,CLI 跨命令即丢失 会话级,可跨批
ISNULL 不存在 存在
TOP n PERCENT / MERGE / TRUNCATE 不支持 支持
触发器伪表 NEW.col / OLD.col inserted / deleted
触发器体 仅 INSERT/UPDATE/DELETE/RAISE,每条前需 AS 引导 任意 T-SQL 块
过程调用 CALL p()(EXEC 只在过程体内) EXEC p
与 SQL Server 一致的部分 NULL 排序(ASC NULL 在前)、TOP、OFFSET/FETCH、[名字]、N'…'、IDENTITY、dbo 之外的常规语法 —

5. 迁移建议

  1. 把 ISNULL 换成 COALESCE;把 TOP n PERCENT 改成先算行数再 LIMIT。
  2. 建表脚本里显式写出可空性:本引擎默认 NOT NULL,与 SQL Server 相反。
  3. 依赖 CHAR(n) 定长语义的列,改用 VARCHAR 并在应用层补位/裁剪。
  4. 长度/精度约束在应用层再校验一遍(VARCHAR(n)、DECIMAL(p,s) 中只有后者生效)。
  5. 双引号标识符改成 [名字] 或裸名字;SET QUOTED_IDENTIFIER 整行删掉。
  6. 触发器重写成 BEFORE|AFTER … AS <stmt> 形式,伪表改 NEW/OLD。
  7. 顶层 EXEC p 改成 CALL p();过程定义补空参数括号。
  8. 去掉 dbo. 前缀与跨库引用。

6. 复现

cd /path/to/dbsql
./target/release/dbsql --root /tmp/dbsql-dialect-verify create database tdb
./target/release/dbsql --root /tmp/dbsql-dialect-verify sql tdb "CREATE TABLE t (id INT PRIMARY KEY, v VARCHAR(5))"
./target/release/dbsql --root /tmp/dbsql-dialect-verify sql tdb "INSERT INTO t (id) VALUES (1)"
# 错误:第 1 行的列 'v' 不允许为空(未提供值且无默认值)

完整清单:verify.sh。