如何在Rust Diesel中用单条更新语句反转布尔字段值?
在Rust Diesel中用单条语句切换SQLite待办事项的完成状态
你已经通过Diesel定义了todos表:
diesel::table! { todos (id) { id -> Integer, parent_id -> Nullable<Integer>, title -> Text, done -> Bool, } }
对应的模型结构体:
#[derive(Queryable, QueryableByName, AsChangeset)] #[diesel(table_name = todos)] pub struct Todo { pub id: i32, pub parent_id: Option<i32>, pub title: String, pub done: bool }
想要实现单条更新语句切换done字段的布尔状态(无需前置查询),对应的原生SQL是UPDATE todos SET done = NOT done WHERE id = ?,之前的写法报错是因为没找对Diesel中处理列表达式取反的方式,正确实现如下:
正确代码实现
需要使用Diesel提供的not函数(来自diesel::dsl模块)来对列表达式进行取反操作:
use diesel::dsl::not; fn toggle_todo_done(conn: &mut SqliteConnection, id: i32) -> Todo { diesel::update(todos.find(id)) .set(done.eq(not(done))) .get_result::<Todo>(conn) .unwrap() }
为什么之前的写法报错?
- 使用
!done时,你是把Diesel的columns::done列表达式当成了普通Rust布尔值,但columns::done的类型并没有实现std::ops::Nottrait,所以无法直接用!运算符取反。 - 使用
done.ne(done)是生成了“不等于自身”的表达式,逻辑上永远为false,而且该表达式类型不符合AsChangeset的要求,因此报错。
效果说明
上述代码会生成你预期的原生SQL语句,直接在数据库层面完成状态切换,无需先查询待办事项再更新,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Simone
相关产品推荐
相关产品推荐

