如何使用sqlx query_as查询模型部分字段并避免报错?
问题描述
我有一张名为order_data的表,包含timestamp类型的created_on字段和i32类型的order_id字段,想用不同方法查询这两个字段。
查询created_on的方法:
pub async fn fetch_last_created_on(pool: &Pool<Postgres>) -> Option<NaiveDateTime> { let result = match query_as::<Postgres, OrderDb>("select max(created_on) as created_on from order_data") .fetch_one(pool) .await { Ok(result) => result.created_on, Err(e) => { error!("Error fetching data: {}", e); None } }; result }
查询order_id的方法:
pub async fn fetch_all_order_ids(pool: &Pool<Postgres>) -> Option<HashSet<i32>> { let result = match query_as::<Postgres, OrderDb>("select order_id from order_data") .fetch_all(pool) .await { Ok(result) => Some(result.iter().map(|order| order.order_id.unwrap()).collect()), Err(e) => { error!("Error fetching data: {}", e); None } }; result }
定义的OrderDb结构体:
#[derive(FromRow)] struct OrderDb { order_id: Option<i32>, created_on: Option<NaiveDateTime>, }
调用fetch_last_created_on时出现错误:
no column found for name: order_id
我可以为每种查询定义单独的#[derive(FromRow)]结构体,但有没有更好的处理方式?注意我不使用宏,仅使用方法。
解决方案
方法一:使用query替代query_as,手动提取字段
放弃依赖FromRow结构体,直接处理查询返回的行数据,按需提取字段,无需为每个查询定义专属结构体。
修改fetch_last_created_on:
pub async fn fetch_last_created_on(pool: &Pool<Postgres>) -> Option<NaiveDateTime> { let result = match query("select max(created_on) as created_on from order_data") .fetch_one(pool) .await { Ok(row) => row.try_get("created_on").ok(), Err(e) => { error!("Error fetching data: {}", e); None } }; result }
修改fetch_all_order_ids:
pub async fn fetch_all_order_ids(pool: &Pool<Postgres>) -> Option<HashSet<i32>> { let result = match query("select order_id from order_data") .fetch_all(pool) .await { Ok(rows) => { let ids: Result<HashSet<i32>, _> = rows.into_iter() .map(|row| row.try_get("order_id")) .collect(); ids.ok() } Err(e) => { error!("Error fetching data: {}", e); None } }; result }
这种方式完全避免了字段不匹配的问题,代码更简洁直接,适合简单查询场景。
方法二:为结构体字段添加#[from_row(default)]属性
如果希望保留OrderDb结构体的复用性,可以给字段添加#[from_row(default)]属性(需确保使用的FromRow实现支持该属性,例如sqlx的FromRow)。当查询结果缺少对应字段时,该字段会自动使用默认值(Option类型即为None),不会抛出错误。
修改后的结构体:
#[derive(FromRow)] struct OrderDb { #[from_row(default)] order_id: Option<i32>, #[from_row(default)] created_on: Option<NaiveDateTime>, }
这样无论查询返回单个字段还是多个字段,结构体都能正常解析,无需额外定义多个结构体。
内容的提问来源于stack exchange,提问作者Enigo
相关产品推荐
相关产品推荐

