数据库
创建 sqlite 数据库
使用rusqlite
箱子,打开 sqlite 数据库。见箱子文档中 Windows 的编译。
Connection::open
:如果数据库不存在,将创建该数据库。
extern crate rusqlite; 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
。此食谱将数据插入到cat_colors
,还有和cats
表用到Connection
的execute
方法。 首先,将数据插入cat_colors
表。插入颜色(color)记录后,Connection
的last_insert_rowid
方法,能获取最后插入(color)的id
。这个id
能用来,把数据插入到cats
表。然后,使用prepare
方法准备查询,它会返回statement
结构。然后,再使用statement
的query_map
方法(进行查询).
extern crate rusqlite; use rusqlite::{Connection, Result}; use rusqlite::NO_PARAMS; 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)。事务将回滚,除非明确使用Transaction::commit
提交。
一次事务,就是一系列对数据库的操作,且明确
commit
后才会执行。
在下面的示例中,将颜色添加表,该表对颜色名称要唯一,进行约束。当尝试插入重复的颜色时,事务将回滚。
extern crate rusqlite; 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() }