Rust Diesel插入数据时Queryable trait未满足错误求助
编译错误(E0277)修复
你遇到的error[E0277]: the trait bound (): diesel::Queryable<(Integer, diesel::sql_types::Text), Pg> is not satisfied错误,核心原因是get_result方法需要明确知道要将数据库返回的行转换为哪种实现了Queryable的类型,而你可能没有指定泛型参数,导致编译器错误推断返回类型为()(空单元)。
修复方法很简单,调用get_result时显式指定你的Deftables结构体作为泛型参数:
use diesel::RunQueryDsl; // 示例插入代码 let new_table = Newtable { /* 填充插入所需字段 */ }; let inserted_row: Deftables = insert_into(deftables::table) .values(&new_table) .get_result(con) .expect("插入数据失败");
这样编译器就能正确识别要转换的类型,满足Queryable trait约束。
是否必须定义两个结构体?如何避免代码重复?
不是必须定义两个结构体,但分开定义是Diesel官方推荐的实践——因为Queryable需要对应表的全部字段(包括数据库自动生成的id这类字段),而Insertable只需要对应插入时需要传入的字段(通常不需要id,因为是自增或数据库生成)。
如果想减少代码重复,可以通过派生宏的属性让单个结构体同时实现两个trait:
use diesel::{Queryable, Insertable}; use crate::schema::deftables; #[derive(Debug, Queryable, Insertable)] #[diesel(table_name = deftables)] #[diesel(insertable(exclude(id)))] // 插入时自动排除id字段 struct Deftables { id: i32, name: String, // 其他表字段 } // 插入时给id设任意值即可,数据库会自动忽略并生成新id let new_table = Deftables { id: 0, name: "测试数据".to_string(), }; let inserted_row = insert_into(deftables::table) .values(&new_table) .get_result::<Deftables>(con)?;
注意:用exclude(id)后,插入时传入的id值会被数据库忽略,若表中有其他数据库生成的字段(如创建时间),也可用同样方式排除。
如何获取新生成的ID?
通过get_result方法返回的Deftables实例就能直接拿到新生成的id——Diesel的get_result会自动使用PostgreSQL的INSERT ... RETURNING *语法,将插入后数据库生成的完整行返回给你,其中就包含自动生成的id字段。
比如上面示例中,inserted_row.id就是新插入数据的ID。
内容的提问来源于stack exchange,提问作者Noh Kumado

