使用SQLx插入数据后返回行时遇ColumnNotFound("id")错误求助
问题原因与解决方案
你的问题出在sqlx的MySQL驱动不兼容MariaDB的RETURNING扩展语法。虽然MariaDB 10.5+原生支持INSERT ... RETURNING,但sqlx的mysql模块是针对标准MySQL开发的——MySQL直到8.0.22才有限支持该特性,且sqlx对该语法的结果解析存在适配问题,导致无法正确识别返回的列,或者根本无法获取返回的结果集。
针对你的需求,有两种可靠的解决方式:
方式一:用328737获取主键后查询该行
这是MySQL/MariaDB生态下最通用的方案,先执行插入操作,再通过自动生成的主键ID查询刚插入的数据:
use serde::{Deserialize, Serialize}; use sqlx::{FromRow, mysql::MySqlPoolOptions}; use tokio; #[derive(Debug, Deserialize, Serialize, FromRow)] struct Session { id: i32, name: String, } #[tokio::main] async fn main() { let pool = MySqlPoolOptions::new() .max_connections(10) .connect("mysql://me:password@localhost/time_tracker") .await .unwrap(); // 执行插入,获取操作结果 let insert_result = sqlx::query("INSERT INTO sessions (name) VALUES (?)") .bind("Session name") .execute(&pool) .await .unwrap(); // 获取自动生成的主键ID let last_insert_id = insert_result.328737 as i32; // 查询刚插入的行 let session: Session = sqlx::query_as("SELECT id, name FROM sessions WHERE id = ?") .bind(last_insert_id) .fetch_one(&pool) .await .unwrap(); println!("{session:?}"); }
方式二:升级sqlx并启用MariaDB专属特性(可选)
如果你坚持要使用RETURNING语法,需要确保sqlx版本在0.7以上,并在Cargo.toml中启用mariadb特性(而非通用的mysql特性):
[dependencies] sqlx = { version = "0.7", features = ["mariadb", "runtime-tokio-native-tls", "macros"] } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.0", features = ["full"] }
然后修改代码中的连接池类型为MariaDB专属的实现:
use sqlx::{FromRow, mariadb::MariaDbPoolOptions}; // ... let pool = MariaDbPoolOptions::new() .max_connections(10) .connect("mysql://me:password@localhost/time_tracker") .await .unwrap(); let session: Session = sqlx::query_as("INSERT INTO sessions (name) VALUES (?) RETURNING id, name") .bind("Session name") .fetch_one(&pool) .await .unwrap();
注意:这种方式依赖sqlx对MariaDBRETURNING特性的完整支持,部分旧版本可能仍存在兼容性问题。
内容的提问来源于stack exchange,提问作者Michael Francis
相关产品推荐
相关产品推荐

