拆分 SQL 文件为独立文件(存储过程、函数、视图、触发器、表结构、索引、约束),自动分析依赖并生成合并脚本
---
name: sql-splitter
description: 拆分 SQL 文件为独立文件(存储过程、函数、视图、触发器、表结构、索引、约束),自动分析依赖并生成合并脚本
---
# SQL 文件拆分工具 v2.4.0
将包含多个 SQL 对象的单一文件或目录拆分为独立的 .sql 文件,
并自动分析对象间依赖关系,生成按依赖排序的合并脚本。
## v2.4.0 新功能 — 达梦数据库转换器重写
- **重写达梦数据库转换器** - 完全重写 dm_converter.py
- token化保护: 字符串/注释替换为占位符后再做正则替换,避免误改字符串内容
- 按对象类型独立转换: procedure/function/view/trigger/table/index/constraint
- 40+种数据类型映射, 30+种函数映射
- 变量语法转换: @var -> var, DECLARE @var -> var, SET @var= -> var:=
- TRY-CATCH -> EXCEPTION WHEN OTHERS THEN
- 全局变量转换: @@ROWCOUNT -> SQL%ROWCOUNT
- 触发器伪表: inserted/deleted -> NEW/OLD
- 转换结果输出到子目录: output_split_dm/
- **拆分后转换集成** - split_sql_v21.py 新增 convert_to 参数
- 拆分完成后自动调用转换器,按对象类型独立转换
- 生成达梦版合并脚本 merge_all.sql
- **CLI参数** - split_sql_v22.py 新增 --convert-to dm
- **29个转换单元测试** - test_dm_converter.py 全部通过
- **修复已知bug**:
- INSERT INTO 不再被误替换为 INTEGERO
- token_map 合并避免占位符还原丢失
- content = new_content 遗漏导致变量@替换无效
- 嵌套括号 VARCHAR(100) 导致参数列表正则截断
- 终止符 / 不再重复添加
### 达梦转换使用方法
```bash
# 拆分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 | INTEGER/TINYINT/TIMESTAMP/DECIMAL(19,4)/VARCHAR |
| 函数 | 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化保护**: 字符串/注释替换为占位符后再做正则替换,避免误改字符串内容
- **token_map合并**: Step2对象类型转换后重新tokenize时,必须合并旧token_map,否则`__TOKEN_0__`等占位符还原丢失
- **变量@前缀**: 在token还原后再做,且用`_tokenize_strings_only`只保护字符串(不保护注释,注释里@变量也要转)
- **`content = new_content` 不可省略**: re.sub后必须更新content变量,否则后续替换基于旧文本
- **嵌套括号**: `VARCHAR(100)`中的`)`会截断`[^)]*`,参数列表匹配需用`(\([^)]*(?:\([^)]*\)[^)]*)*\))`匹配嵌套
- **数据类型上下文**: 前缀需包含`DECLARE\s+`,否则`DECLARE @v DATETIME`中的DATETIME不会被转换
- **INSERT INTO误匹配**: `INSERT INT`被匹配为前缀`\n`+列名`INSERT`+类型`INT`,需在数据类型替换中排除SQL关键字作为列名
### 运行转换测试
```bash
cd ~/.openclaw/skills/sql-splitter/scripts
python3 -m pytest test_dm_converter.py -v
```
## 支持的 SQL 方言
- MySQL
- PostgreSQL
- Oracle
- SQL Server
- 达梦 (DM)
- 通用 (Generic)
## v2.2.1 功能
- **GUI 界面** - 提供图形化界面进行 SQL 文件拆分操作
- **断点续传** - 支持记录处理进度,中断后可以继续处理
- **批量并行处理** - 支持同时处理多个 SQL 文件,提升处理速度
- **结果预览和对比** - 可视化查看拆分结果,支持与原始文件对比
- **配置文件管理** - 保存和加载常用配置,支持导入导出
- **详细错误处理** - 结构化错误信息,包含错误类型、上下文和修复建议
- **Dry-run 预览模式** - 预览拆分结果而不实际创建文件
- **安全修复** - pickle反序列化漏洞修复,检查点改用JSON序列化
## 支持的 SQL 对象类型
| 类型 | 前缀 | 说明 |
|------|------|------|
| 存储过程 | `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 |
## v2.0 核心改进
### 边界检测重写
- 使用 **BEGIN...END 深度匹配**确定存储过程/函数/触发器边界
- 支持 IF...THEN...END IF、CASE...END CASE、LOOP...END LOOP 嵌套
- 不再依赖"下一个 CREATE 位置"做上界,**正确处理过程体内的嵌套 CREATE 语句**
- Oracle/DM: 通过 `/` 终止符定位;SQL Server: 通过 `GO` 定位
- PostgreSQL: 支持 `$$...$$` 包裹语法
- 字符串和注释内的分号/关键字不会干扰边界检测
### 依赖分析改进
- 函数调用检测改为**限定上下文模式**(:= 赋值、WHERE/HAVING 子句等),大幅减少误报
- SQL 关键字过滤表扩展到 150+ 个,涵盖内置函数、控制流、聚合等
- 自引用自动排除
- 循环依赖不再报错,按类型优先级追加
### 合并脚本方言适配
- Oracle/DM: `@@filename` + `SET DEFINE OFF`
- SQL Server: `:r filename` + `GO`
- PostgreSQL: `\i filename` + `ON_ERROR_STOP`
- MySQL: `source filename`
- 通用: 注释方式
### 架构优化
- 提取 `common.py` 共享模块:SQLDialect 枚举、对象前缀、类型优先级、关键字表
- `dependency_analyzer.py` 不再重复定义枚举,直接引用 common
- 拆分后自动调用依赖分析,生成 `merge_all.sql`
- 新增 37 个单元测试
## 使用方法
### GUI 模式(推荐)
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/gui.py
```
### 单文件拆分
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py <input.sql> [output_dir]
```
### 批量拆分(目录)
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --batch <目录路径> [输出目录]
```
### 批量拆分(多个文件)
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --batch "file1.sql,file2.sql,file3.sql" [输出目录]
```
### 指定方言
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --dialect oracle input.sql
```
支持的方言:`mysql`, `postgresql`, `oracle`, `sqlserver`, `dm`, `generic`
### 不生成合并脚本
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --no-merge input.sql
```
### 预览结果
```bash
python3 ~/.openclaw/skills/sql-splitter/scripts/split_sql_v22.py --preview input.sql output_dir
```
### 检查点管理
```bash
# 列出所有检查点
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
```
### 配置管理
```bash
# 列出所有配置
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) |
### 运行测试
```bash
cd ~/.openclaw/skills/sql-splitter/scripts
# 拆分测试
python3 -m unittest test_sql_splitter -v
# 达梦转换测试
python3 -m pytest test_dm_converter.py -v
```
## 输出示例
假设输入文件 `myapp.sql` 包含:
- 表 `users`
- 视图 `v_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 为例):
```sql
-- [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 ← 达梦转换器设计要点
└── 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个)
```
## 注意事项
- 使用正则+深度匹配识别 SQL 对象边界,对极复杂嵌套语法可能有局限
- 默认 UTF-8 编码,遇到编码问题自动 replace
- 建议先备份原文件
- 批量模式会自动创建以原文件名命名的子目录
- 自动检测 SQL 方言,也可手动指定
- 同名文件自动追加序号(如 `proc_sp_init_2.sql`)
## 常见问题
### 拆分结果不正确(多个对象混在一个文件中)
**症状**:拆分后生成的文件包含多个 SQL 对象,而不是每个对象一个文件。
**原因**:原始 SQL 文件中的对象缺少分号结束符。sql-splitter 依赖分号来确定对象的结束位置。
**解决方案**:为每个 SQL 语句添加分号。例如:
```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)
);
```
**快速修复方法**:
```bash
# 使用 sed 为每个 CREATE 语句后的空行添加分号
sed -i '' '/^Create /,/^)/s/)$/);/' input.sql
```
### 视图未被识别
**症状**:拆分后没有生成视图文件,或视图被识别为其他对象类型。
**原因**:视图语法不规范,缺少 `AS` 关键字。
**解决方案**:修正视图语法,添加 `AS` 关键字。例如:
```sql
-- 错误:缺少 AS
create view v_a
(
select * from dual
);
-- 正确:添加 AS
CREATE VIEW v_a AS
SELECT * FROM dual;
```
### 存储过程/函数未被正确拆分
**症状**:多个存储过程混在一个文件中,或产生重复文件。
**原因**:存储过程语法不规范,缺少 `AS`/`BEGIN` 关键字或分隔符。
**解决方案**:根据数据库类型修正语法:
**SQL Server**:
```sql
-- 错误:缺少 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/达梦**:
```sql
-- 错误:缺少 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**:
```sql
-- 错误:缺少 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`)。
**原因**:对象边界检测失败,通常由以下原因导致:
- 对象之间缺少分隔符(分号、GO、/ 等)
- 对象语法不规范(缺少 AS、BEGIN 等)
- 嵌套对象语法错误
**解决方案**:
1. 检查并修正原始 SQL 文件的语法
2. 确保每个对象之间有正确的分隔符
3. 使用 `--dialect` 参数明确指定数据库类型
4. 对于复杂情况,考虑手动拆分或使用数据库工具导出
### 预检查清单
在运行 sql-splitter 之前,建议检查以下内容:
- [ ] 每个 SQL 语句都有分号结束符
- [ ] 视图包含 `AS` 关键字
- [ ] 存储过程/函数包含 `AS`/`BEGIN` 关键字
- [ ] SQL Server 对象之间有 `GO` 分隔符
- [ ] Oracle/达梦 对象末尾有 `/` 终止符
- [ ] MySQL 存储过程使用 `DELIMITER`
- [ ] 对象名称没有特殊字符或保留字冲突
- [ ] 文件编码为 UTF-8
## 更新日志
### v2.4.0 (2026-05-23)
- **重写达梦数据库转换器** - 完全重写 dm_converter.py
- token化保护: 字符串/注释替换为占位符后再做正则替换
- 按对象类型独立转换: procedure/function/view/trigger/table/index/constraint
- 40+种数据类型映射, 30+种函数映射
- 变量语法转换: @var -> var, DECLARE @var -> var, SET @var= -> var:=
- TRY-CATCH -> EXCEPTION WHEN OTHERS THEN
- 全局变量转换: @@ROWCOUNT -> SQL%ROWCOUNT
- 触发器伪表: inserted/deleted -> NEW/OLD
- 转换结果输出到子目录: output_split_dm/
- **拆分后转换集成** - split_sql_v21.py 新增 convert_to 参数
- 拆分完成后自动调用转换器,按对象类型独立转换
- 生成达梦版合并脚本 merge_all.sql
- **CLI参数** - split_sql_v22.py 新增 --convert-to dm
- **29个转换单元测试** - test_dm_converter.py 全部通过
- **修复已知bug**:
- INSERT INTO 不再被误替换为 INTEGERO
- token_map 合并避免占位符还原丢失
- content = new_content 遗漏导致变量@替换无效
- 嵌套括号 VARCHAR(100) 导致参数列表正则截断
- 终止符 / 不再重复添加
### v2.2.1 (2026-05-01)
- **安全修复** - 修复 pickle 反序列化漏洞
- 将检查点文件序列化从 pickle 替换为 JSON
- 添加数据验证,防止恶意数据注入
- 所有测试通过,功能正常
- **新增安全文档** - 添加 SECURITY.md
- 详细说明安全措施和最佳实践
- 记录安全更新历史
- 提供安全问题报告渠道
- **新增依赖管理** - 添加 requirements.txt
- 明确列出所有依赖
- 当前版本仅使用 Python 标准库
- 减少供应链攻击风险
### v2.2.0 (2026-04-27)
- **新增 GUI 界面** - 提供图形化界面进行 SQL 文件拆分操作
- 支持文件浏览、参数配置、进度显示
- 实时输出日志和错误信息
- 配置自动保存和加载
- **新增断点续传功能** - 支持记录处理进度,中断后可以继续处理
- 自动保存处理进度到检查点文件
- 支持查看恢复进度和状态
- 支持清理旧检查点
- **新增批量并行处理** - 支持同时处理多个 SQL 文件,提升处理速度
- 可配置最大并发数
- 支持目录批量处理
- 支持进度回调
- **新增结果预览和对比** - 可视化查看拆分结果,支持与原始文件对比
- 生成详细的文件统计信息
- 支持表格化显示
- 支持与原始文件内容对比
- **新增配置文件管理** - 保存和加载常用配置,支持导入导出
- 支持多配置管理
- 支持 JSON/YAML 格式导入导出
- 配置验证功能
### v2.0.2 (2026-04-24)
- **修复重复文件问题**:添加去重逻辑,避免同一对象被多个正则表达式重复匹配
- 去重标准:相同起始位置、对象类型、对象名称
- 解决 SQL Server 存储过程产生重复文件的问题
- 新增去重功能测试用例
### v2.0.1 (2026-04-24)
- 文档更新:新增常见问题章节
- 视图未被识别的解决方案(缺少 AS 关键字)
- 存储过程/函数未被正确拆分的解决方案(缺少 AS/BEGIN/分隔符)
- 产生重复文件的原因和解决方案
- 预检查清单(运行前检查项)
### v2.0.0 (2026-04-19)
- 重写对象边界检测:BEGIN/END/IF/CASE/LOOP 深度匹配
- 不再依赖"下一个 CREATE"作为上界,修复嵌套 CREATE 截断问题
- 提取 `common.py` 共享模块,消除枚举重复定义
- 依赖分析器:限定上下文检测、扩展关键字过滤、自引用排除
- 合并脚本按方言适配(Oracle/SQL Server/PostgreSQL/MySQL/DM)
- 拆分后自动生成 merge_all.sql
- 新增 37 个单元测试
- SQL Server 正则修复:方括号标识符匹配
### v1.1.0 (2026-04-13)
- 新增索引支持:CREATE INDEX, CREATE UNIQUE INDEX
- 新增约束支持:ALTER TABLE ADD CONSTRAINT
- 所有 6 种方言均支持索引/约束识别
- 支持 CLUSTERED/NONCLUSTERED (SQL Server)
- 支持 BITMAP 索引 (Oracle/达梦)
### v1.0.0
- 初始版本don't have the plugin yet? install it then click "run inline in claude" again.