2 个版本 (1 个稳定版)
1.0.0 | 2020年8月13日 |
---|---|
0.0.0 | 2020年4月25日 |
#2030 在 数据库接口
39KB
567 行
rsqlite
此库是一个无开销、高效的 sqlite C API 包装器。
// creates a database file 'dbfile.db' if it does not exists.
let database = Database::open("dbfile.db")?;
// executes the query and creates a 'user' table
database.execute(r#"
create table if not exists user (
id integer primary key autoincrement not null,
age int,
name text,
weight real
);"#, ())?;
// inserts a new user record.
// binds the fields to '?' .
// note that only these types are allowed for bindings:
// int32, i64, f64, &str, &[u8]
// use `&[u8]` to store blob data.
database.execute(
"insert into user(age, name, weight) values(?, ?, ?)",
(29, "amin", 69.5)
)?;
let name = String::from("negar");
database.execute(
"insert into user(age, name, weight) values(?, ?, ?)",
(26, name.as_str(), 61.0)
)?;
// slects from user table on a condition ( age > 27 ),
// and executes the closure for each row returned.
database.for_each(
"select name, age, weight from user where age > ?", (27),
|name: String, age: i32, weight: f64| {
dbg!(name, age, weight);
}
)?;
// selects the count(*) from user table
// you can extract a single culumn single row result to:
// i32, i64, f64, String, Box<[u8]>
let count: i32 = database.collect("select count(*) from user", ())?;
// you can also extract single row with multiple columns
let amin: (i32, String, f64) = database.collect(
"select age, name, weight from user where name = ?", ("amin")
)?;
// this also works, the returned value will be automatically converted to String
let str_count: String = database.collect("select count(*) from user", ())?;
额外标志
你可以向 SQLite 传递额外的打开标志
[dependencies]
sqlite3-sys = "*"
use rsqlite::{ffi, Database};
let flags = ffi::SQLITE_READONLY;
let database = Database::open_with_flags("dbfile.db", flags)?;
// now you can only read from the database
let n: i32 = database.collect(
"select a from table where something >= ?", (1))?;
预处理语句
可以保留和重用语句,这会保持查询计划,如果语句被重用,可能会显著提高性能。
let mut statement = database.prepare("select age from user where age > ?")?;
// Database methods are simply implemented in terms of statements.
statement.for_each((27), |age: i32| {
dbg!(age);
})?;
let age: i32 = database.prepare("select count(*) from user where age > ? limit 1")?
.collect((200))?;
NULL 值
如果你有可空的列,你可以使用 Option<T>
来传递和收集值。
// use `None` to insert NULL values
database.execute("insert into user(name, age) values (?,?)", (None::<&str>, 20))?;
// use Option<T> to collect them back
let (name, age) : (Option<String>, i32) =
database.collect("select name, age from user limit 1", ())?;
assert!((name, age) == (None, 20));
// an empty result set, would also be treated as None
let name : Option<String> = database.collect("select name from user where age = ?", (200))?;
assert!(name == None);
类型转换
sqlite 中的隐式类型转换遵循以下表格:例如,如果你收集一个 NULL
列作为 i32
,你将得到 0
。
内部类型 | 请求的类型 | 转换 |
---|---|---|
NULL | i32/i64 | 结果是 0 |
NULL | f64 | 结果是 0.0 |
NULL | String | 结果是空 String::new() |
NULL | Box<[u8]> | 结果是空的 Box::new([]) |
INTEGER | f64 | 从整数转换为 f64 |
INTEGER | String | 整数的 ASCII 表示 |
INTEGER | Box<[u8]> | 与 INTEGER->String 相同 |
FLOAT | i32/i64 | 转换为 INTEGER |
FLOAT | String | 浮点的 ASCII 表示 |
FLOAT | Box<[u8]> | 转换为 [u8] |
TEXT | i32/i64 | 转换为 i32/i64 |
TEXT | f64 | 转换为 f64 |
TEXT | Box<[u8]> | 无变化 |
BLOB | i32/i64 | 转换为 i32/i64 |
BLOB | f64 | 转换为 f64 |
BLOB | String | 无变化 |
事务
你可以使用 begin
、commit
和 rollback
命令来使用事务。
database.execute("begin", ())?; // begin a transaction ...
let mut statement = database.prepare("insert into user(name, age) values (?, ?)")?;
// insert 10 users using a prepared statement
for age in 0..10 {
let name = format!("user-{}", age);
statement.execute((name.as_str(), age))?;
}
database.execute("commit", ())?; // commit all the changes
database.execute("begin", ())?; // begin another transaction ...
database.execute("delete from user where age > ?", (3))?;
database.execute("rollback", ())?; // cancel this transaction
let sum_age : i32 = database.collect("select sum(age) from user", ())?;
assert!(sum_age == 45);
Blob
使用 &[u8]
来存储,使用 Box<[u8]>
来检索 blob 数据。
database.execute("create table user (name TEXT, numbers BLOB)", ())?;
let numbers = vec![1, 1, 2, 3, 5];
database.execute("insert into user values (?, ?)", ("amin", numbers.as_slice()))?;
let stored_numbers : Box<[u8]> =
database.collect("select numbers from user where name = ?", ("amin"))?;
assert!(numbers.as_slice() == stored_numbers.as_ref());
许可证
MIT 许可证 - http://www.opensource.org/licenses/mit-license.php
依赖项
~0.5–1MB
~25K SLoC