Rust SQL查询构建器sql-builder的使用,高效生成安全动态SQL语句的Rust库
Rust SQL查询构建器sql-builder的使用,高效生成安全动态SQL语句的Rust库
简单的SQL代码生成器。
使用方法
在Cargo.toml
中添加以下依赖:
[dependencies]
sql-builder = "3.1"
示例
SELECT查询
use sql_builder::SqlBuilder;
let sql = SqlBuilder::select_from("company")
.field("id")
.field("name")
.and_where_gt("salary", 25_000)
.sql()?;
assert_eq!("SELECT id, name FROM company WHERE salary > 25000;", &sql);
use sql_builder::prelude::*;
let sql = SqlBuilder::select_from("company")
.fields(&["id", "name"])
.and_where("salary BETWEEN ? AND ?".binds(&[&10_000, &25_000]))
.and_where("staff BETWEEN ? AND ?".bind(&100).bind(&200))
.sql()?;
assert_eq!("SELECT id, name FROM company WHERE (salary BETWEEN 10000 AND 25000) AND (staff BETWEEN 100 AND 200);", &sql);
INSERT插入
use sql_builder::{SqlBuilder, quote};
let sql = SqlBuilder::insert_into("company")
.field("name")
.field("salary")
.field("staff")
.values(&["e("D&G"), &10_000.to_string(), &100.to_string()])
.values(&["e("G&D"), &25_000.to_string(), &200.to_string()])
.sql()?;
assert_eq!("INSERT INTO company (name, salary, staff) VALUES ('D&G', 10000, 100), ('G&D', 25000, 200);", &sql);
use sql_builder::prelude::*;
let sql = SqlBuilder::insert_into("company")
.field("name")
.field("salary")
.field("staff")
.values(&["$1, ?, ?"])
.values(&["$2, ?, ?"])
.sql()?
.bind_nums(&[&"D&G", &"G&D"])
.binds(&[&10_000, &100]);
assert_eq!("INSERT INTO company (name, salary, staff) VALUES ('D&G', 10000, 100), ('G&D', 10000, 100);", &sql);
UPDATE更新
use sql_builder::SqlBuilder;
let sql = SqlBuilder::update_table("company")
.set("salary", "salary + 100")
.and_where_lt("salary", 1_000)
.sql()?;
assert_eq!("UPDATE company SET salary = salary + 100 WHERE salary < 1000;", &sql);
use sql_builder::prelude::*;
let sql = SqlBuilder::update_table("company")
.set("salary", "salary + $1")
.set("comment", "e("up $1$$"))
.and_where("salary < ?".bind(&1_000))
.sql()?
.bind_nums(&[&100]);
assert_eq!("UPDATE company SET salary = salary + 100, comment = 'up 100$' WHERE salary < 1000;", &sql);
DELETE删除
use sql_builder::SqlBuilder;
let sql = SqlBuilder::delete_from("company")
.or_where_lt("salary", 1_000)
.or_where_gt("salary", 25_000)
.sql()?;
assert_eq!("DELETE FROM company WHERE salary < 1000 OR salary > 25000;", &sql);
use sql_builder::prelude::*;
use std::collections::HashMap;
let mut names: HashMap<&str, &dyn SqlArg> = HashMap::new();
names.insert("min", &1_000);
names insert("max", &25_000);
let sql = SqlBuilder::delete_from("company")
.and_where("salary >= :min:")
.and_where("salary <= :max:")
.sql()?
.bind_names(&names);
assert_eq!("DELETE FROM company WHERE (salary >= 1000) AND (salary <= 25000);", &sql);
完整示例
以下是一个更完整的示例,展示如何使用sql-builder构建复杂的动态SQL查询:
use sql_builder::prelude::*;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 构建带条件的SELECT查询
let mut params = HashMap::new();
params.insert("min_salary", &60000);
params.insert("dept", &"Engineering");
let sql = SqlBuilder::select_from("employees as e")
.distinct()
.fields(&["e.id", "e.name", "d.name as dept_name"])
.left_join("departments as d", "e.dept_id = d.id")
.and_where("e.salary > :min_salary:")
.and_where("d.name = :dept:")
.group_by("e.id, e.name, d.name")
.having("COUNT(*) > 0")
.order_by("e.name", Some("ASC"))
.limit(20)
.offset(10)
.sql()?
.bind_names(¶ms);
println!("复杂查询SQL:\n{}", sql);
// 构建批量INSERT操作
let new_employees = vec![
("王伟", "研发部", 85000),
("李娜", "市场部", 75000),
("张强", "财务部", 90000)
];
let mut insert_sql = SqlBuilder::insert_into("employees")
.fields(&["name", "department", "salary"]);
for emp in new_employees {
insert_sql = insert_sql.values(&[
"e(emp.0), // 姓名需要引号包裹
"e(emp.1), // 部门需要引号包裹
&emp.2.to_string() // 薪资直接转字符串
]);
}
println!("批量插入SQL:\n{}", insert_sql.sql()?);
// 构建UPDATE操作
let update_sql = SqlBuilder::update_table("employees")
.set("salary", "salary * 1.1") // 涨薪10%
.and_where("department = ?".bind(&"研发部"))
.and_where("hire_date < ?".bind(&"2020-01-01"))
.sql()?;
println!("更新SQL:\n{}", update_sql);
Ok(())
}
SQL支持功能
支持的语句
- SELECT
- INSERT
- UPDATE
- DELETE
支持的操作
- 表连接(join)
- 去重(distinct)
- 分组(group by)
- 排序(order by)
- 条件过滤(where)
- 联合查询(union)
- 分页(limit, offset)
- 子查询(subquery)
支持的功能
- 特殊字符转义(escape)
- 多种引号处理(quote, double quote, back quote, brackets quote)
- 多种参数绑定方式(bind, binds, bind_num, bind_nums, bind_name, bind_names)
许可证
本项目采用MIT许可证。
1 回复
Rust SQL查询构建器sql-builder的使用
介绍
sql-builder是一个Rust库,用于高效生成安全的动态SQL语句。它提供了类型安全的SQL构建方式,可以帮助开发者避免SQL注入攻击,同时简化复杂SQL语句的构建过程。
主要特点:
- 类型安全的SQL构建
- 支持动态条件拼接
- 自动参数化查询,防止SQL注入
- 支持多种SQL方言
- 轻量级且无运行时开销
安装
在Cargo.toml中添加依赖:
[dependencies]
sql-builder = "3.0"
基本使用方法
1. 构建简单查询
use sql_builder::SqlBuilder;
let sql = SqlBuilder::select_from("books")
.field("title")
.field("author")
.and_where("price > 100")
.order_by("published_at", false) // false表示降序
.limit(10)
.offset(5)
.sql()
.unwrap();
println!("{}", sql);
// 输出: SELECT title, author FROM books WHERE price > 100 ORDER BY published_at DESC LIMIT 10 OFFSET 5
2. 使用参数化查询
use sql_builder::SqlBuilder;
let sql = SqlBuilder::select_from("users")
.field("id")
.field("name")
.and_where("age > ?".bind(&30))
.and_where("status = ?".bind(&"active"))
.sql()
.unwrap();
println!("{}", sql);
// 输出: SELECT id, name FROM users WHERE age > 30 AND status = 'active'
3. 构建复杂查询
use sql_builder::SqlBuilder;
let min_price = 50;
let max_price = 200;
let category = "programming";
let sql = SqlBuilder::select_from("books")
.field("title")
.field("author")
.field("price")
.join("categories", "books.category_id = categories.id")
.and_where("price BETWEEN ? AND ?".bind(&min_price).bind(&max_price))
.and_where("categories.name = ?".bind(&category))
.group_by("author")
.having("COUNT(*) > 1")
.sql()
.unwrap();
println!("{}", sql);
// 输出: SELECT title, author, price FROM books JOIN categories ON books.category_id = categories.id
// WHERE price BETWEEN 50 AND 200 AND categories.name = 'programming' GROUP BY author HAVING COUNT(*) > 1
4. 构建INSERT语句
use sql_builder::SqlBuilder;
let sql = SqlBuilder::insert_into("users")
.field("name")
.field("age")
.field("email")
.values(&["'John Doe'".into(), "30".into(), "'john@example.com'".into()])
.sql()
.unwrap();
println!("{}", sql);
// 输出: INSERT INTO users (name, age, email) VALUES ('John Doe', 30, 'john@example.com')
5. 构建UPDATE语句
use sql_builder::SqlBuilder;
let sql = SqlBuilder::update_table("users")
.set("name", "'Jane Doe'")
.set("age", "31")
.and_where("id = 1")
.sql()
.unwrap();
println!("{}", sql);
// 输出: UPDATE users SET name = 'Jane Doe', age = 31 WHERE id = 1
高级用法
动态条件拼接
use sql_builder::SqlBuilder;
fn build_query(name_filter: Option<&str>, min_age: Option<i32>) -> String {
let mut builder = SqlBuilder::select_from("users")
.field("*");
if let Some(name) = name_filter {
builder.and_where(format!("name LIKE '%{}%'", name));
}
if let Some(age) = min_age {
builder.and_where(format!("age >= {}", age));
}
builder.sql().unwrap()
}
println!("{}", build_query(Some("John"), Some(30)));
// 输出: SELECT * FROM users WHERE name LIKE '%John%' AND age >= 30
使用不同的SQL方言
use sql_builder::{SqlBuilder, quote};
let sql = SqlBuilder::select_from("books")
.field("title")
.field("author")
.and_where(format!("category = {}", quote("fiction")))
.sql()
.unwrap();
println!("{}", sql);
// 输出: SELECT title, author FROM books WHERE category = 'fiction'
完整示例
下面是一个完整的示例,展示了如何使用sql-builder构建各种SQL语句:
use sql_builder::{SqlBuilder, quote};
fn main() {
// 1. 简单查询示例
let simple_query = SqlBuilder::select_from("products")
.field("id")
.field("name")
.field("price")
.and_where("stock > 0")
.order_by("price", true) // true表示升序
.sql()
.unwrap();
println!("简单查询:\n{}\n", simple_query);
// 2. 参数化查询示例
let min_price = 100;
let category = "electronics";
let param_query = SqlBuilder::select_from("products")
.field("*")
.and_where("price > ?".bind(&min_price))
.and_where("category = ?".bind(&category))
.sql()
.unwrap();
println!("参数化查询:\n{}\n", param_query);
// 3. 复杂查询示例
let complex_query = SqlBuilder::select_from("orders")
.field("orders.id")
.field("customers.name")
.field("SUM(order_items.quantity * order_items.price) AS total")
.join("customers", "orders.customer_id = customers.id")
.join("order_items", "orders.id = order_items.order_id")
.and_where("orders.date > '2023-01-01'")
.group_by("orders.id, customers.name")
.having("total > 1000")
.sql()
.unwrap();
println!("复杂查询:\n{}\n", complex_query);
// 4. INSERT语句示例
let insert_query = SqlBuilder::insert_into("users")
.field("username")
.field("email")
.field("created_at")
.values(&["'testuser'".into(), "'test@example.com'".into(), "CURRENT_TIMESTAMP".into()])
.sql()
.unwrap();
println!("INSERT语句:\n{}\n", insert_query);
// 5. UPDATE语句示例
let update_query = SqlBuilder::update_table("products")
.set("price", "price * 1.1") // 涨价10%
.and_where("category = 'premium'")
.sql()
.unwrap();
println!("UPDATE语句:\n{}\n", update_query);
// 6. 动态条件拼接示例
let dynamic_query = build_dynamic_query(Some("apple"), Some(2.5), None);
println!("动态查询:\n{}\n", dynamic_query);
}
fn build_dynamic_query(
name_filter: Option<&str>,
min_price: Option<f64>,
max_price: Option<f64>,
) -> String {
let mut builder = SqlBuilder::select_from("products")
.field("*");
if let Some(name) = name_filter {
builder.and_where(format!("name LIKE '%{}%'", name));
}
if let Some(price) = min_price {
builder.and_where(format!("price >= {}", price));
}
if let Some(price) = max_price {
builder.and_where(format!("price <= {}", price));
}
builder.sql().unwrap()
}
注意事项
- 虽然sql-builder可以帮助防止SQL注入,但仍需谨慎处理用户输入
- 复杂的SQL可能需要手动编写
- 对于大型项目,可能需要考虑使用ORM如Diesel或SQLx
sql-builder特别适合需要动态构建SQL查询的场景,它提供了比原始字符串拼接更安全、更易维护的方式。