编译期检查查询
类型安全的 SQL
编译期检查查询 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
核心优势
sqlx 可以在编译时根据真实数据库架构验证您的 SQL。拼写错误、错误的列名和类型不匹配都会变成构建错误。
- 使用
query!宏系列 - 在运行时之前捕获错误
query! 与 query
query() 函数会在运行时检查。query! 宏会在构建期间连接数据库,从而在编译时检查。
use sqlx::{Pool, Postgres};
async fn run(pool: &Pool<Postgres>) {
let rec = sqlx::query!("SELECT id, name FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap();
}类型化的结果字段
query! 宏会生成一个匿名结构体,其字段与选中的列相匹配,并根据架构推断出正确的 Rust 类型。
use sqlx::{Pool, Postgres};
async fn name_of(pool: &Pool<Postgres>, id: i32) -> String {
let rec = sqlx::query!("SELECT name FROM users WHERE id = $1", id)
.fetch_one(pool)
.await
.unwrap();
rec.name
}检查的工作方式
构建时,sqlx 需要一个可用的 DATABASE_URL,或者一个已缓存的 .sqlx 目录。它会将查询发送到数据库,以了解参数和结果的类型。
使用 cargo sqlx prepare 的离线模式
对于没有数据库的持续集成环境,请运行 cargo sqlx prepare,将查询元数据保存到 .sqlx/ 中。之后构建过程会使用该缓存。
cargo sqlx prepare将 query_as! 映射到您的结构体
使用 query_as! 将行直接映射到您定义的结构体中,同时仍然进行完整检查。
use sqlx::{Pool, Postgres};
struct User { id: i32, name: String }
async fn get(pool: &Pool<Postgres>) -> User {
sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap()
}可空列会变成 Option
如果某列可能为 NULL,sqlx 会将对应字段设为 Option。您可以使用 name as "name!" 这样的类型注解覆盖推断结果。
use sqlx::{Pool, Postgres};
async fn maybe_email(pool: &Pool<Postgres>) -> Option<String> {
let rec = sqlx::query!("SELECT email FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap();
rec.email
}模拟类型推断
编译时检查会将 SQL 类型映射为 Rust 类型。这个可运行示例模拟了这一映射决策。
fn rust_type(sql: &str, nullable: bool) -> String {
let base = match sql {
"int4" => "i32",
"text" => "String",
"bool" => "bool",
_ => "unknown",
};
if nullable { format!("Option<{}>", base) } else { base.to_string() }
}
fn main() {
println!("{}", rust_type("int4", false));
println!("{}", rust_type("text", true));
}您将看到的编译错误
如果引用了不存在的列,sqlx 会显示清晰的消息并使构建失败。这种安全性正是这些宏的全部意义。
- 列名错误 → 编译时错误
- 类型不匹配 → 编译时错误
绑定参数按位置对应
对于 Postgres,请使用 $1、$2 占位符。sqlx 会根据架构检查每个绑定参数的类型。
use sqlx::{Pool, Postgres};
async fn search(pool: &Pool<Postgres>, name: &str, min_age: i32) {
let _ = sqlx::query!(
"SELECT id FROM users WHERE name = $1 AND age >= $2",
name, min_age
).fetch_all(pool).await.unwrap();
}何时使用非宏形式
对于在运行时构建的动态 SQL(事先不知道列),请使用 query() / query_as()。这样会牺牲编译时检查,换取灵活性。
use sqlx::{Pool, Postgres};
async fn dynamic(pool: &Pool<Postgres>, sql: &str) {
let _ = sqlx::query(sql).execute(pool).await.unwrap();
}快速检查
检验您对编译时检查的理解。
回顾
您已经学习了编译时检查的查询:
query!和query_as!会在构建时根据架构验证 SQL- 结果字段及其类型会自动推断
- 可空列会变成
Option cargo sqlx prepare支持离线构建- 对于动态 SQL,请使用非宏形式的
query()
下一步:CRUD 操作。
常见问题解答
「编译期检查查询」课时是免费的吗?
是的 — 「编译期检查查询」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「编译期检查查询」这节课中我会学到什么?
类型安全的 SQL 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「编译期检查查询」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。