28个版本 (10个稳定版)
2.3.0 | 2024年7月21日 |
---|---|
2.1.0 | 2023年12月11日 |
2.0.0 | 2023年9月30日 |
1.1.4 | 2023年5月30日 |
0.10.5 | 2022年7月27日 |
#74 in 数据库接口
2,587 每月下载量
在 3 个Crates中使用了(b 2 直接)
165KB
2.5K SLoC
以简单和可组合的方式编写SQL查询。
主要目标是找到编写惯用SQL查询和管理混合条件语句的复杂查询组合场景之间的最佳平衡。
快速入门
use sql_query_builder as sql;
let mut select = sql::Select::new()
.select("id, login")
.from("users")
.where_clause("login = $1");
let is_admin = true;
if is_admin {
select = select.where_clause("is_admin = true");
}
let query = select.as_string();
println!("{}", query);
输出
SELECT id, login FROM users WHERE login = $1 AND is_admin = true
功能标志
SQL Query Builder附带以下可选功能
postgresql
启用Postgres语法sqlite
启用SQLite语法
您可以使用以下功能
# Cargo.toml
sql_query_builder = { version = "2.x.x", features = ["postgresql"] }
工作原理
简单来说,该库有一个API,允许您以类似于纯SQL编写的查询风格编写动态查询,结果是与Rust和SQL都符合代码习惯的代码。此外,库不会尝试理解您在参数中写入的内容,这在某种程度上是好的,因为它减少了生成SQL查询的冗余,相比之下,调试通常更困难,可能会出现一些愚蠢的错误,库有一个debug()方法,它提供了良好的输出以最大限度地减少调试复杂查询的努力。
更技术地说,对同一子句的连续调用将累积值,并尊重调用顺序,两个select生成相同的SQL查询。
use sql_query_builder as sql;
let select = sql::Select::new()
.select("id, login");
let select = sql::Select::new()
.select("id")
.select("login");
如limit
和offset
这样的方法将覆盖前一个值,两个select是等效的
# #[cfg(any(feature = "postgresql", feature = "sqlite"))]
# {
use sql_query_builder as sql;
let select = sql::Select::new()
.limit("1000")
.limit("123");
let select = sql::Select::new()
.limit("123");
# }
库忽略子句之间的顺序,因此两个select将生成相同的查询
use sql_query_builder as sql;
let select = sql::Select::new()
.select("id, login")
.from("users")
.where_clause("login = $1");
let select = sql::Select::new()
.from("users")
.where_clause("login = $1")
.select("id, login");
您可以通过修改select来条件性地添加子句
use sql_query_builder as sql;
let mut select = sql::Select::new()
.select("id, login")
.from("users")
.where_clause("login = $1");
let should_includes_address = true;
if should_includes_address {
select = select.inner_join("addresses on user.login = addresses.owner_login");
}
组合
组合对于编写复杂查询非常受欢迎,这个功能使得库更加出色
use sql_query_builder as sql;
fn project(select: sql::Select) -> sql::Select {
select
.select("u.id, u.name as user_name, u.login")
.select("a.name as addresses_name")
.select("o.name as product_name")
}
fn relations(select: sql::Select) -> sql::Select {
select
.from("users u")
.inner_join("addresses a ON a.user_login = u.login")
.inner_join("orders o ON o.user_login = u.login")
}
fn conditions(select: sql::Select) -> sql::Select {
select
.where_clause("u.login = $1")
.where_clause("o.id = $2")
}
fn as_string(select: sql::Select) -> String {
select.as_string()
}
let query = Some(sql::Select::new())
.map(project)
.map(relations)
.map(conditions)
.map(as_string)
.unwrap();
println!("{query}");
输出(缩进以提高可读性)
SELECT u.id, u.name as user_name, u.login, a.name as addresses_name, o.name as product_name
FROM users u
INNER JOIN addresses a ON a.user_login = u.login
INNER JOIN orders o ON o.user_login = u.login
WHERE u.login = $1 AND o.id = $2
原始查询
您可以使用原始方法来访问一些难以用Select语法重写的边缘情况。 select.raw()
方法将把您定义的任何SQL放在输出的顶部
use sql_query_builder as sql;
let raw_query = "\
select u.id as user_id, addr.* \
from users u \
inner join addresses addr on u.login = addr.owner_login\
";
let select = sql::Select::new()
.raw(raw_query)
.where_clause("login = $1");
为了更精确地使用,您可以使用 select.raw_before()
和 select.raw_after()
use sql_query_builder as sql;
let raw_query = "\
from users u \
inner join addresses addr on u.login = addr.owner_login\
";
let select = sql::Select::new()
.select("u.id as user_id, addr.*")
.raw_before(sql::SelectClause::Where, raw_query)
.where_clause("login = $1");
use sql_query_builder as sql;
let raw_query = "\
from users u \
inner join addresses addr on u.login = addr.owner_login\
";
let select = sql::Select::new()
.select("u.id as user_id, addr.*")
.raw_after(sql::SelectClause::Select, raw_query)
.where_clause("login = $1");
调试查询
有时直接打印查询构建器的当前状态会更加方便。为此,在任何地方添加 .debug()
方法。以下示例中,由于在子句之前添加了 debug,因此 where 子句将不会被打印。
use sql_query_builder as sql;
let mut select = sql::Select::new()
.select("id, login")
.from("users")
.debug()
.where_clause("login = $1");
打印到标准输出
-- ------------------------------------------------------------------------------
SELECT id, login
FROM users
-- ------------------------------------------------------------------------------