Install
openclaw skills install sql-splitter拆分 SQL 文件为独立文件(存储过程、函数、视图、触发器、表结构、索引、约束),自动分析依赖并生成合并脚本
openclaw skills install sql-splitter将包含多个 SQL 对象的单一文件或目录拆分为独立的 .sql 文件, 并自动分析对象间依赖关系,生成按依赖排序的合并脚本。
方括号→双引号 - [schema].[table] → "schema"."table"
普通标识符 [Users] → "Users"
SQL类型名 [nvarchar] → nvarchar(去掉方括号+类型映射,不会变成"nvarchar")
支持30+种SQL Server类型名识别
dbo前缀智能处理 - 根据三段式/两段式自动判断
三段式 [HRBI].[dbo].[Users] → "HRBI"."Users"(有schema前缀时,删除dbo.)
两段式 [dbo].[Users] → hrbi_stage."Users"(无schema前缀时,用源文件名替换dbo)
schema_prefix从源文件名自动提取(如hrbi_stage.sql → 前缀hrbi_stage)
支持双引号包裹格式:"dbo"."Users" 和裸名格式:dbo.Users 均可正确匹配
精确拆分增强 - 无明确终止符时的兜底逻辑
新增_find_next_create函数:当找不到;或GO终止符时,用下一个CREATE关键字作为对象边界上界
跳过字符串和注释内的CREATE,只匹配真正的CREATE语句开头
所有对象类型(table/view/procedure/function/trigger/index/constraint)均有兜底
VARCHAR CHAR语义后处理 - VARCHAR(n) → VARCHAR(n CHAR)
修复detokenize中类型名映射绕过CHAR语义的问题
重写达梦数据库转换器 - 完全重写 dm_converter.py
拆分后转换集成 - split_sql_v21.py 新增 convert_to 参数
CLI参数 - split_sql_v22.py 新增 --convert-to dm
29个转换单元测试 - test_dm_converter.py 全部通过
修复已知bug:
# 拆分SQL Server文件并转换为达梦数据库语法
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py input.sql output_dir --dialect sqlserver --convert-to dm
# 仅转换(不拆分)
python3 -c "from dm_converter import convert_sqlserver_to_dm; print(convert_sqlserver_to_dm('SELECT GETDATE()', 'generic'))"
| 类别 | SQL Server | 达梦 |
|---|---|---|
| 声明 | CREATE PROCEDURE ... AS | CREATE OR REPLACE PROCEDURE ... IS |
| 数据类型 | INT/BIT/DATETIME/MONEY/NVARCHAR/VARCHAR/UNIQUEIDENTIFIER | INTEGER/BOOLEAN/TIMESTAMP/DECIMAL(19,4)/VARCHAR(n CHAR)/CHAR(36) |
| 函数 | GETDATE()/ISNULL()/LEN()/CONVERT() | CURRENT_TIMESTAMP/NVL()/LENGTH()/CAST() |
| 变量 | @var / DECLARE @var / SET @var= | var / var / var:= |
| 异常 | BEGIN TRY...END TRY BEGIN CATCH...END CATCH | BEGIN...EXCEPTION WHEN OTHERS THEN...END; |
| 事务 | COMMIT TRANSACTION / ROLLBACK TRANSACTION | COMMIT / ROLLBACK |
| 全局变量 | @@ROWCOUNT / @@ERROR | SQL%ROWCOUNT / SQL%ERROR_CODE |
| 触发器 | inserted/deleted | NEW/OLD |
| 终止符 | GO | / |
input_split/ ← 原始拆分结果
├── proc_sp_test.sql
├── table_users.sql
├── view_v_users.sql
└── merge_all.sql
input_split_dm/ ← 达梦转换版本
├── proc_sp_test.sql
├── table_users.sql
├── view_v_users.sql
└── merge_all.sql
| 对象类型 | 转换策略 |
|---|---|
| 存储过程 | CREATE OR REPLACE + IS + 参数@去除 + 终止符/ |
| 函数 | CREATE OR REPLACE + RETURN + IS + 终止符/ |
| 视图 | CREATE OR REPLACE + SCHEMABINDING去除 |
| 触发器 | CREATE OR REPLACE + inserted/deleted->NEW/OLD + 终止符/ |
| 表 | IDENTITY保留 + 表选项去除 + 类型映射 |
| 索引 | CLUSTERED/NONCLUSTERED去除 + INCLUDE去除 |
| 约束 | WITH NOCHECK去除 |
__TOKEN_0__等占位符还原丢失_tokenize_strings_only只保护字符串(不保护注释,注释里@变量也要转)content = new_content 不可省略: re.sub后必须更新content变量,否则后续替换基于旧文本VARCHAR(100)中的)会截断[^)]*,参数列表匹配需用(\([^)]*(?:\([^)]*\)[^)]*)*\))匹配嵌套DECLARE\s+,否则DECLARE @v DATETIME中的DATETIME不会被转换INSERT INT被匹配为前缀\n+列名INSERT+类型INT,需在数据类型替换中排除SQL关键字作为列名xxd或sed -n 'Np' file | xxd确认原始缩进的精确空格/tab数,再写Python脚本逐行替换lines[N] = '正确缩进内容\n'。每次patch后必须用python3 -m py_compile dm_converter.py验证。仅靠lint不够——py_compile才能发现缩进导致的SyntaxError/IndentationError__pycache__/*.pyc。修改后必须find . -name '*.pyc' -delete或PYTHONDONTWRITEBYTECODE=1 python3 -m pytest ...。否则改了代码但测试结果不变,误导调试方向NNN|行号前缀,导致Python文件损坏。代码文件只能用patch工具或terminal的python脚本修改。详见 v2.4.3修复记录cd ~/.openclaw/skills/sql-splitter/scripts
python3 -m pytest test_dm_converter.py -v
| 类型 | 前缀 | 说明 |
|---|---|---|
| 存储过程 | proc_ | CREATE PROCEDURE |
| 函数 | func_ | CREATE FUNCTION |
| 视图 | view_ | CREATE VIEW |
| 触发器 | trig_ | CREATE TRIGGER |
| 表结构 | table_ | CREATE TABLE |
| 包 | pkg_ | CREATE PACKAGE |
| 索引 | idx_ | CREATE INDEX |
| 唯一索引 | uidx_ | CREATE UNIQUE INDEX |
| 约束 | con_ | ALTER TABLE ADD CONSTRAINT |
| 序列 | seq_ | CREATE SEQUENCE |
| 同义词 | syn_ | CREATE SYNONYM (Oracle) |
| 事件 | evt_ | CREATE EVENT (MySQL) |
| 物化视图 | mv_ | CREATE MATERIALIZED VIEW (PostgreSQL) |
| 类型 | type_ | CREATE TYPE |
/ 终止符定位;SQL Server: 通过 GO 定位$$...$$ 包裹语法@@filename + SET DEFINE OFF:r filename + GO\i filename + ON_ERROR_STOPsource filenamecommon.py 共享模块:SQLDialect 枚举、对象前缀、类型优先级、关键字表dependency_analyzer.py 不再重复定义枚举,直接引用 commonmerge_all.sqlpython3 ~/.openclaw/skills/sql-splitter/scripts/gui.py
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py <input.sql> [output_dir]
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --batch <目录路径> [输出目录]
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --batch "file1.sql,file2.sql,file3.sql" [输出目录]
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --dialect oracle input.sql
支持的方言:mysql, postgresql, oracle, sqlserver, dm, generic
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --no-merge input.sql
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --preview input.sql output_dir
# 列出所有检查点
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --checkpoint --list
# 查看恢复进度
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --checkpoint --resume input.sql
# 清理旧检查点
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --checkpoint --clear --days 7
# 删除检查点
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --checkpoint --delete input.sql
# 列出所有配置
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --config --list
# 保存配置
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --config --save --name oracle --dialect oracle
# 加载配置
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --config --load --name oracle
# 导出配置
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --config --export --name oracle --export-path oracle_config.json
# 导入配置
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --config --import --import-path oracle_config.json --name oracle
| 参数 | 说明 |
|---|---|
input.sql | 要拆分的 SQL 文件路径(单文件模式必需) |
--batch | 批量模式标志 |
--dialect | 指定 SQL 方言 |
--no-merge | 不生成依赖排序的合并脚本 |
-q, --quiet | 静默模式 |
output_dir | 输出目录(可选,默认:原文件名_split) |
cd ~/.openclaw/skills/sql-splitter/scripts
# 拆分测试
python3 -m unittest test_sql_splitter -v
# 达梦转换测试
python3 -m pytest test_dm_converter.py -v
假设输入文件 myapp.sql 包含:
usersv_users(依赖 users)sp_update(依赖 users)输出:
myapp_split/
├── table_users.sql
├── view_v_users.sql
├── proc_sp_update.sql
└── merge_all.sql ← 按依赖排序的合并脚本
merge_all.sql 内容(以 Oracle 为例):
-- [1/3] table: users
@@table_users.sql
-- [2/3] view: v_users -- depends on: users
@@view_v_users.sql
-- [3/3] procedure: sp_update -- depends on: users
@@proc_sp_update.sql
sql-splitter/
├── SKILL.md ← 本文档
├── V21_USAGE_GUIDE.md ← v2.1 使用指南
├── SECURITY.md ← 安全文档
├── requirements.txt ← 依赖
├── references/
│ ├── dm-converter-design.md ← 达梦转换器设计要点
│ └── dm-converter-v243-fixes.md ← v2.4.3 修复记录
└── scripts/
├── common.py ← 共享模块(枚举、常量、工具函数)
├── split_sql.py ← v2.0 主拆分脚本
├── split_sql_v21.py ← v2.1 主拆分脚本(带错误处理+转换集成)
├── split_sql_v22.py ← v2.2 主拆分脚本(集成所有新功能)
├── dm_converter.py ← 达梦数据库转换器 v2.0
├── dependency_analyzer.py ← 依赖分析器
├── error_handler.py ← 错误处理模块
├── gui.py ← GUI 界面
├── checkpoint.py ← 断点续传模块
├── batch_processor.py ← 批量并行处理模块
├── result_previewer.py ← 结果预览和对比模块
├── config_manager.py ← 配置文件管理模块
├── test_sql_splitter.py ← 拆分单元测试(37个)
├── test_v21_features.py ← v2.1 功能测试
└── test_dm_converter.py ← 达梦转换单元测试(29个)
v2.4.3 修复了 9 个核心 BUG(DATEADD参数重排、SELECT INTO、IF/WHILE控制流、PRINT等),40个测试全部通过。详见 v2.4.3修复记录
仍需手动调整的项目:
v2.4.4 已修复的映射:
CREATE 转为 CREATE OR REPLACEOR REPLACE,否则会报错OR REPLACE 的语句不会重复添加obj_content 提取后、写入文件前proc_sp_init_2.sql)症状:拆分后生成的文件包含多个 SQL 对象,而不是每个对象一个文件。
原因:原始 SQL 文件中的对象缺少分号结束符。sql-splitter 依赖分号来确定对象的结束位置。
解决方案:为每个 SQL 语句添加分号。例如:
-- 错误:缺少分号
Create table a(
Id int,
Name varchar(10)
)
Create table b(
Id int,
Name varchar(10)
)
-- 正确:添加分号
Create table a(
Id int,
Name varchar(10)
);
Create table b(
Id int,
Name varchar(10)
);
快速修复方法:
# 使用 sed 为每个 CREATE 语句后的空行添加分号
sed -i '' '/^Create /,/^)/s/)$/);/' input.sql
症状:拆分后没有生成视图文件,或视图被识别为其他对象类型。
原因:视图语法不规范,缺少 AS 关键字。
解决方案:修正视图语法,添加 AS 关键字。例如:
-- 错误:缺少 AS
create view v_a
(
select * from dual
);
-- 正确:添加 AS
CREATE VIEW v_a AS
SELECT * FROM dual;
症状:多个存储过程混在一个文件中,或产生重复文件。
原因:存储过程语法不规范,缺少 AS/BEGIN 关键字或分隔符。
解决方案:根据数据库类型修正语法:
SQL Server:
-- 错误:缺少 AS 和 GO
create proc p_a
(
select * from dual
);
create proc p_b
(
select * from dual
);
-- 正确:添加 AS 和 GO
CREATE PROCEDURE p_a
AS
BEGIN
SELECT * FROM dual;
END
GO
CREATE PROCEDURE p_b
AS
BEGIN
SELECT * FROM dual;
END
GO
Oracle/达梦:
-- 错误:缺少 IS/AS 和 /
CREATE PROCEDURE p_a
BEGIN
SELECT * FROM dual;
END
-- 正确:添加 IS/AS 和 /
CREATE OR REPLACE PROCEDURE p_a IS
BEGIN
SELECT * FROM dual;
END;
/
MySQL:
-- 错误:缺少 DELIMITER
CREATE PROCEDURE p_a()
BEGIN
SELECT * FROM dual;
END
-- 正确:使用 DELIMITER
DELIMITER //
CREATE PROCEDURE p_a()
BEGIN
SELECT * FROM dual;
END //
DELIMITER ;
症状:拆分后生成多个内容相同或相似的文件(如 proc_p_a.sql 和 proc_p_a_2.sql)。
原因:对象边界检测失败,通常由以下原因导致:
解决方案:
--dialect 参数明确指定数据库类型在运行 sql-splitter 之前,建议检查以下内容:
AS 关键字AS/BEGIN 关键字GO 分隔符/ 终止符DELIMITER[schema].[table] → "schema"."table",类型名[nvarchar] → nvarchar(去掉方括号并做类型映射)[HRBI].[dbo].[Users] → "HRBI"."Users"(删dbo);两段式[dbo].[Users] → hrbi_stage."Users"(用文件名替换);/GO终止符时,用下一个CREATE关键字作为对象边界兜底DECLARE @v1 INT, @v2 VARCHAR(100) 正确拆分为多行独立声明common.py 共享模块,消除枚举重复定义