你以为 ORM 只能靠运行才发现 SQL 写错了?今天 SQLx 用编译期检查把这件事彻底变了

写过 Rust 后端的人都踩过这个坑——SQL 字符串写进代码里,到底有没有语法错误、有没有拼错列名、类型对不对得上,只能等运行的时候数据库报错才恍然大悟。特别是 CI 跑完、上了生产,突然一条查询崩了,那感觉就像考试铃响了才发现答案写在草稿纸上。

这件事被 SQLx 0.9(2026 年 5 月发布)彻底原生化了——它让你写 SQL 不用二选一:要么放弃类型安全靠 ORM,要么放弃 SQL 靠 query builder。SQLx 给你第三条路:直接写 SQL,编译期检查

query!宏:连接一次数据库,换一辈子的编译时安心

SQLx 的核心是 query! 宏家族。编译时,它会真正连接你的开发数据库(PostgreSQL / MySQL / SQLite),让数据库本身验证 SQL 语法是否正确、列名存不存在、参数类型和返回值能不能对上。整个过程不需要任何 DSL,直接写原始 SQL 字符串:

“`rust
let rec = sqlx::query!(
“SELECT id, name, email FROM users WHERE id = $1”,
user_id
)
.fetch_one(&pool)
.await?;
println!(“{}!”, rec.name);
“`

如果 SQL 有问题——比如 $1 传了 &str 但数据库期待 i64——cargo build 直接失败,报错信息直接告诉你第几行、哪个字段、类型不匹配。数据库连接只在本地编译时用一次,生产构建不需要。

离线模式:CI 构建不需要数据库也能验证

团队协作时,不能要求每个开发者的机器都连着数据库,CI 服务器更不可能。SQLx 支持离线模式:

“`bash
cargo sqlx prepare
SQLX_OFFLINE=true cargo build
“`

每次 schema 变更后跑 cargo sqlx prepare --check,CI 就能发现缓存过期、阻止带病代码合并。「SQL 写错了,上线才知道」变成了「commit 没更新缓存,CI 就拦住」。

Rust 工具链视角:比 ORM 快,比 query builder 安全

SQLx Diesel SeaORM
抽象程度 直接写 SQL 类型化 query builder ORM(关系映射)
SQL 检查 编译期(需 DB) 编译期(DSL) 运行时
异步 原生 async/await 同步 原生 async/await
学习曲线 只需懂 SQL 需学 DSL 需学 ORM 概念

你真正要注意的坑

query! 需要数据库连接才能编译,这意味着没有 .sqlx 缓存时 CI 构建必须有数据库。常见误区是「编译过了就是安全的」——实际上缓存不更新,schema 改了 SQL 没改,还是会放行。建议把 cargo sqlx prepare --check 单独一个 CI job,专门盯缓存有效性。

第二个坑是 nullable 处理:数据库 nullable 字段映射到 Rust 需要用 Option<T>,加了 ? 才不会编译报错。切过来第一天会多不少 ? 操作符,但这是值得的。

下一步

cargo install sqlx-cli 开始,跑一次 sqlx database create,在迁移文件里把 schema 定好。schema 敲定了,query! 写 SQL 的时候心里就踏实了——写错了 cargo build 拦住你,不会在凌晨三点让用户看到 500。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 10 阅读