如何在Rust的sqlx::query_with中同时获取rows_affected与查询结果?
同时获取受影响行数与查询结果的方法
针对PostgreSQL + sqlx的场景,无需执行两次查询就能同时拿到受影响行数和结果的核心思路是利用PostgreSQL的RETURNING子句,结合sqlx查询对象的rows_affected()方法实现:
修改SQL语句,添加
RETURNING子句
对于INSERT/UPDATE/DELETE这类DML语句,通过RETURNING指定需要返回的列,让数据库在执行操作的同时返回被修改的行数据。示例SQL:UPDATE users SET email = $1 WHERE id = $2 RETURNING id, name, email;用
fetch_one/fetch_all获取结果,再调用rows_affected()拿行数
执行fetch类方法获取结果集后,通过查询对象的rows_affected()方法直接获取受影响的行数,无需额外查询。
代码示例
假设你有一个User结构体,在事务中执行更新操作并同时获取结果和行数:
use sqlx::{Postgres, Transaction}; #[derive(Debug, sqlx::FromRow)] struct User { id: i32, name: String, email: String, } async fn update_user( tx: &mut Transaction<'_, Postgres>, user_id: i32, new_email: &str, ) -> Result<(Option<User>, u64), sqlx::Error> { // 构建带RETURNING的查询 let mut query = sqlx::query_as!( User, "UPDATE users SET email = $1 WHERE id = $2 RETURNING id, name, email", new_email, user_id ); // 获取查询结果(按ID更新最多返回一行,用fetch_optional处理无匹配的情况) let result = query.fetch_optional(tx).await?; // 获取受影响行数 let rows_affected = query.rows_affected(); Ok((result, rows_affected)) }
关键说明
RETURNING是PostgreSQL原生特性,确保DML操作返回被修改的行,避免二次查询。- sqlx的查询对象在执行
fetch_*方法后,会保留数据库返回的受影响行数信息,通过rows_affected()可直接读取,无需额外调用execute。 - 该方法完全支持事务场景,不会破坏事务原子性,也不需要并行执行事务。
内容的提问来源于stack exchange,提问作者TachyonicBytes
相关产品推荐
相关产品推荐

