如何在rustqlite中获取可为空或空值的列数据?
解决rusqlite处理NULL TEXT字段的panic问题
错误原因
你遇到的InvalidColumnType(0, "name", Null)错误,是因为数据库中name字段为NULL,但你直接用row.get(0).unwrap()尝试将其转换为String——而Rust的String不允许为NULL,rusqlite无法完成这个转换,因此触发panic。
解决方案
核心思路是用Option<String>接收数据库返回的字段值(NULL对应None),再将None转为你需要的空字符串,具体实现如下:
修改后的代码
use rusqlite::{Connection, Result}; fn main() -> Result<()> { // Open connection let conn = Connection::open(":memory:")?; // Create test_table conn.execute( "CREATE TABLE IF NOT EXISTS test_table ( id INTEGER PRIMARY KEY, name TEXT )", (), )?; // Insert demo row conn.execute("INSERT INTO test_table (id) VALUES (?1)", [1])?; // Prepare an empty vector to store column data even if is empty string let mut result: Vec<String> = Vec::new(); // The actual query conn.query_row("SELECT name FROM test_table WHERE id = ?1", [1], |row| { // 将字段值转为Option<String>,NULL对应None let name: Option<String> = row.get(0)?; // 把None替换成空字符串,存入vector result.push(name.unwrap_or_default()); Ok(()) })?; println!("Result: {:?}", result); Ok(()) }
关键修改点
- 用
Option<String>接收row.get(0)的结果:rusqlite会自动将数据库TEXT类型的NULL映射为None,非NULL值映射为Some(String)。 - 使用
unwrap_or_default()将None转为空字符串(String::default()就是空字符串),满足你需要存储空字符串的需求。 - 全程用
?替代unwrap()处理错误,避免不必要的panic,同时让代码更简洁。
关于循环的疑问
你提到想用while+match处理结果,但query_row本身就是用于获取单行数据的API,不需要循环。如果要处理多行数据,应该用query方法配合迭代器:
// 处理多行的示例 let mut stmt = conn.prepare("SELECT name FROM test_table")?; let name_iter = stmt.query_map([], |row| { let name: Option<String> = row.get(0)?; Ok(name.unwrap_or_default()) })?; for name in name_iter { result.push(name?); }
内容的提问来源于stack exchange,提问作者trwartek
相关产品推荐
相关产品推荐

