自定义 SQL 本地开发使用教程
这篇文档面向日常开发者,目标是把平台上的自定义 SQL 纳入本地项目维护:在本地创建、拉取、编辑、校验、推送、执行验证和删除,减少“平台上改了一版、本地不知道”的漂移。
适用场景:
- 需要写复杂查询、跨表统计、报表 SQL。
- 需要把已有平台 SQL 拉到本地长期维护。
- 需要让 SQL 文件进入代码评审、版本管理或 AI Agent 工作流。
- 需要在推平台前先做本地校验和变更预览。
不适用场景:
- 简单数据 CRUD,优先用 SDK
filter/getOne/create/update/delete。 - 简单分组汇总,优先考虑 SDK
aggregate。 - 跨系统调用、事务编排、复杂业务逻辑,优先用 BFF。
1. 准备工作
确认当前项目已经有 .rabetbase.json,并且默认应用正确:
rabetbase app list --format json如果一个项目配置了多个应用,先切换到你要操作的应用:
rabetbase app use <appName>也可以不切默认应用,直接给单条命令加:
--app <appName>
# 或
--appcode <appCode>确认当前 CLI 的 SQL 命令:
rabetbase sql --help当前推荐主流程是:
list/detail -> create 或 pull -> 编辑本地文件 -> validate -> status -> push -> exec -> delete2. 本地目录约定
CLI 会把 SQL 文件维护在项目根目录的:
.rabetbase/sql/<appCode>/<dbName|db-<id>>/<sqlCode>_<sqlName>.sql|xml例如:
.rabetbase/sql/app-xxxxxxxx/order_db/2305f915-dd48cd4c_getOrderList.sql
.rabetbase/sql/app-xxxxxxxx/db-10001/2305f915-dd48cd4c_getOrderMapper.xml同时会维护一个锁文件:
.rabetbase/sql.lock.json锁文件记录:
- 远端 SQL 的
remoteId sqlCode- 当前文件路径
- SQL 名称
- 绑定数据库
- 本地 hash
- 远端版本号
开发者一般只需要编辑 .sql/.xml 文件,不要手动改 sql.lock.json。
3. 查看平台上已有 SQL
先列出 SQL:
rabetbase sql list --format json按名称搜索:
rabetbase sql list --name 用户 --format json查看详情:
rabetbase sql detail --sqlcode <sqlCode> --format json如果需要完整原始对象:
rabetbase sql detail --sqlcode <sqlCode> --verbose --format json建议:不知道 sqlCode 时,先 list --name;拿到 sqlCode 后再 detail。
4. 新建一条 SQL
新建 SQL 使用:
rabetbase sql create --name <sqlName> --db-id <dbId> --mode sql --yes --format jsonMyBatis XML 模式:
rabetbase sql create --name <sqlName> --db-id <dbId> --mode mybatisXml --yes --format json正式执行前可以先预览:
rabetbase sql create --name <sqlName> --db-id <dbId> --mode sql --dry-run --format json创建成功后,CLI 会:
- 在平台创建 SQL。
- 拿到服务端生成的
sqlCode。 - 在
.rabetbase/sql/<appCode>/<dbName|db-<id>>/生成本地文件。 - 写入
.rabetbase/sql.lock.json。
生成的本地文件会带 @lovrabet 头注释,例如:
-- @lovrabet.sqlCode: 2305f915-dd48cd4c
-- @lovrabet.sqlName: getUserList
-- @lovrabet.dbId: 10001
-- @lovrabet.dbName: order_db
-- @lovrabet.mode: sql
-- @lovrabet.syncedAt: 2026-04-20T10:00:00.000Z
SELECT 1 AS id;这些头注释用于本地识别和排查,sql push 上传时会自动剥离,不会写回平台 SQL 正文。
5. 拉取已有 SQL 到本地
如果 SQL 已经在平台上存在,先拉到本地再修改:
rabetbase sql pull --sqlcode <sqlCode> --format json也可以按名称批量拉取:
rabetbase sql pull --name 用户 --format json先预览会写哪些文件:
rabetbase sql pull --sqlcode <sqlCode> --dry-run --format json如果本地文件和远端不一致,默认不会覆盖,会返回类似:
local differs from remote确认要以远端覆盖本地时,再执行:
rabetbase sql pull --sqlcode <sqlCode> --force --format json注意:--force 会覆盖本地未推送修改,使用前建议先看:
rabetbase sql status --format json6. 编辑 SQL 文件
直接编辑生成或拉取下来的 .sql/.xml 文件。
普通 SQL 示例:
SELECT
id,
username,
phone
FROM app_user
WHERE status = #{status}
ORDER BY create_time DESC;MyBatis XML 示例:
<select id="query" resultType="map">
SELECT
id,
username,
phone
FROM app_user
WHERE 1 = 1
<if test="status != null">
AND status = #{status}
</if>
ORDER BY create_time DESC
</select>参数建议统一使用 #{paramName}。后续执行时,--params 的 key 要和 SQL 里的参数名一致。
7. 推送前先校验
校验本地文件:
rabetbase sql validate --file ./.rabetbase/sql/<appCode>/<dbName>/<sqlCode>_<sqlName>.sql --format json也可以直接校验一段 SQL:
rabetbase sql validate --sql "SELECT * FROM app_user WHERE id = #{id}" --format json校验会检查:
- SQL 类型,如
SELECT/INSERT/UPDATE/DELETE/DDL - 是否包含危险语句
- 引用的表名
#{param}/${param}参数
需要结合数据集做表名/列名交叉检查时:
rabetbase sql validate --file <filePath> --schemas <datasetCode1>,<datasetCode2> --format json建议:写完 SQL 先 validate,再 status,最后 push。
8. 查看本地状态
查看当前应用下 SQL 文件状态:
rabetbase sql status --format json输出分类:
| 分类 | 含义 | 常见处理 |
|---|---|---|
added | 本地有,但 lock 里没有 | 确认是否应通过 sql create 或 sql pull 建立同步关系 |
modified | 本地文件相对 lock 有变化 | 先 validate,再 push --dry-run |
missing | lock 里有,但本地文件丢了 | 可重新 sql pull --sqlcode <code> |
unchanged | 本地和 lock 一致 | 通常无需处理 |
remoteOnly | 远端有,本地/lock 没有 | 加 --remote 时检查,按需 pull |
检查远端独有 SQL:
rabetbase sql status --remote --format json9. 推送修改到平台
先预览:
rabetbase sql push --sqlcode <sqlCode> --dry-run --format json确认后正式推送:
rabetbase sql push --sqlcode <sqlCode> --yes --format json不传 --sqlcode 会扫描当前应用本地同步目录下所有 SQL:
rabetbase sql push --dry-run --format json如果本地 hash 和 lock 一致但仍想强制推:
rabetbase sql push --sqlcode <sqlCode> --force --yes --format json推送成功后,CLI 会:
- 上传 SQL/XML 正文到平台。
- 自动剥离本地
@lovrabet头注释。 - 刷新
sql.lock.json中的 hash、路径、版本号等。
10. 执行验证
无参数执行:
rabetbase sql exec --sqlcode <sqlCode> --format json带参数执行:
rabetbase sql exec --sqlcode <sqlCode> --params '{"status":1}' --format json返回通常包含:
{
"rows": [],
"rowCount": 0,
"elapsed": 123
}建议:每次 push 后至少执行一次 exec,确认 SQL 参数、字段和返回结构符合调用方预期。
11. 删除 SQL
先预览:
rabetbase sql delete --sqlcode <sqlCode> --dry-run --format json确认后删除:
rabetbase sql delete --sqlcode <sqlCode> --yes --format json删除成功后:
- 平台 SQL 会被删除。
- 本地 SQL 文件会移动到
.rabetbase/sql-trash/。 sql.lock.json中对应条目会被移除。
删除后建议确认:
rabetbase sql list --name <sqlName> --format json
rabetbase sql status --format json12. sql save 已废弃
旧流程里可能会看到:
rabetbase sql save --file ...当前不要再用它作为新建或修改入口。现在迁移为:
# 新建
rabetbase sql create --name <sqlName> --db-id <dbId> --mode sql|mybatisXml --yes
# 修改
rabetbase sql push --sqlcode <sqlCode> --yes如果执行 sql save,CLI 只会返回迁移提示,不会实际保存。
13. 推荐开发 SOP
新建 SQL:
rabetbase sql create --name getUserList --db-id 10001 --mode sql --dry-run --format json
rabetbase sql create --name getUserList --db-id 10001 --mode sql --yes --format json
rabetbase sql validate --file ./.rabetbase/sql/<appCode>/<dbName>/<sqlCode>_getUserList.sql --format json
rabetbase sql status --format json
rabetbase sql push --sqlcode <sqlCode> --dry-run --format json
rabetbase sql push --sqlcode <sqlCode> --yes --format json
rabetbase sql exec --sqlcode <sqlCode> --params '{"status":1}' --format json修改已有 SQL:
rabetbase sql list --name getUserList --format json
rabetbase sql pull --sqlcode <sqlCode> --format json
rabetbase sql validate --file ./.rabetbase/sql/<appCode>/<dbName>/<sqlCode>_getUserList.sql --format json
rabetbase sql status --format json
rabetbase sql push --sqlcode <sqlCode> --dry-run --format json
rabetbase sql push --sqlcode <sqlCode> --yes --format json
rabetbase sql exec --sqlcode <sqlCode> --params '{"status":1}' --format json删除 SQL:
rabetbase sql delete --sqlcode <sqlCode> --dry-run --format json
rabetbase sql delete --sqlcode <sqlCode> --yes --format json14. 常见问题
14.1 不知道 db-id 怎么找
如果你已经知道要用哪个数据库,但不知道 ID,可以先看平台数据库配置,或者让团队在项目说明里记录常用 dbId。
如果只是维护已有 SQL,优先 sql pull,CLI 会按远端 SQL 里的 dbId 生成目录。
14.2 local differs from remote
说明本地文件与远端内容不一致。先判断方向:
- 要保留本地修改:执行
sql push --sqlcode <sqlCode> --dry-run,确认后--yes。 - 要放弃本地修改:执行
sql pull --sqlcode <sqlCode> --force。
14.3 missing remote version
说明 lock 里没有远端版本号。先执行:
rabetbase sql pull --sqlcode <sqlCode> --force --format json再重新修改和 push。
14.4 本地改了文件名会怎样
文件名中的 <sqlName> 会被视为当前 SQL 名称。只改文件名也会被 sql status 识别为 modified,执行 sql push 后会同步更新远端 SQL 名称。
14.5 换数据库目录会怎样
如果把文件从一个数据库目录移动到另一个数据库目录,sql push 会尝试按目录名重新解析目标 dbId,并同步远端绑定。目录名建议使用 CLI 生成的名称,不要随意改成无法识别的名字。
14.6 什么时候用 --force
只在明确要覆盖本地或强制重新推送时使用:
sql pull --force:用远端覆盖本地。sql push --force --yes:即使本地 hash 看起来没变,也强制推送。
15. 总结
开发者日常只需要记住:
新建用 create,修改用本地文件 + push,拉远端用 pull,提交前先 validate 和 status,sql save 不再使用。本地自定义 SQL 使用教程