SQLite
创建 SQLite 数据库
使用 rusqlite
crate 打开 SQLite 数据库连接。Windows 上编译 rusqlite
crate 请参考文档。
如果数据库不存在,Connection::open
方法将创建它。
use rusqlite::{Connection, Result}; use rusqlite::NO_PARAMS; fn main() -> Result<()> { let conn = Connection::open("cats.db")?; conn.execute( "create table if not exists cat_colors ( id integer primary key, name text not null unique )", NO_PARAMS, )?; conn.execute( "create table if not exists cats ( id integer primary key, name text not null, color_id integer not null references cat_colors(id) )", NO_PARAMS, )?; Ok(()) }
数据插入和查询
Connection::open
将打开在前一章节实例中创建的数据库 cats
的连接。下面的实例使用 Connection
的 execute
方法将数据插入 cat_colors
和 cats
两张表中。首先,将数据插入到 cat_colors
表中。随后,使用 Connection
的 last_insert_rowid
方法来获取 cat_colors
表最后插入记录的 id
。当向 cats
表中插入数据时,使用此 id
。然后,使用 prepare
方法准备执行 select 查询操作,该方法提供 statement
结构体。最后,使用 statement
的 query_map
方法执行查询。
use rusqlite::NO_PARAMS; use rusqlite::{Connection, Result}; use std::collections::HashMap; #[derive(Debug)] struct Cat { name: String, color: String, } fn main() -> Result<()> { let conn = Connection::open("cats.db")?; let mut cat_colors = HashMap::new(); cat_colors.insert(String::from("Blue"), vec!["Tigger", "Sammy"]); cat_colors.insert(String::from("Black"), vec!["Oreo", "Biscuit"]); for (color, catnames) in &cat_colors { conn.execute( "INSERT INTO cat_colors (name) values (?1)", &[&color.to_string()], )?; let last_id: String = conn.last_insert_rowid().to_string(); for cat in catnames { conn.execute( "INSERT INTO cats (name, color_id) values (?1, ?2)", &[&cat.to_string(), &last_id], )?; } } let mut stmt = conn.prepare( "SELECT c.name, cc.name from cats c INNER JOIN cat_colors cc ON cc.id = c.color_id;", )?; let cats = stmt.query_map(NO_PARAMS, |row| { Ok(Cat { name: row.get(0)?, color: row.get(1)?, }) })?; for cat in cats { println!("Found cat {:?}", cat); } Ok(()) }
事务处理
Connection::open
将打开来自前述实例的数据库 cats.db
。
使用 Connection::transaction
开始事务,除非使用 Transaction::commit
显式提交,否则事务将回滚。
在下面的实例中,颜色表对颜色名称具有唯一性约束。当尝试插入重复的颜色时,事务会回滚。
use rusqlite::{Connection, Result, NO_PARAMS}; fn main() -> Result<()> { let mut conn = Connection::open("cats.db")?; successful_tx(&mut conn)?; let res = rolled_back_tx(&mut conn); assert!(res.is_err()); Ok(()) } fn successful_tx(conn: &mut Connection) -> Result<()> { let tx = conn.transaction()?; tx.execute("delete from cat_colors", NO_PARAMS)?; tx.execute("insert into cat_colors (name) values (?1)", &[&"lavender"])?; tx.execute("insert into cat_colors (name) values (?1)", &[&"blue"])?; tx.commit() } fn rolled_back_tx(conn: &mut Connection) -> Result<()> { let tx = conn.transaction()?; tx.execute("delete from cat_colors", NO_PARAMS)?; tx.execute("insert into cat_colors (name) values (?1)", &[&"lavender"])?; tx.execute("insert into cat_colors (name) values (?1)", &[&"blue"])?; tx.execute("insert into cat_colors (name) values (?1)", &[&"lavender"])?; tx.commit() }