启用rust-postgres特性获取PostgreSQL JSON结果时遇列不存在错误
问题原因
你遇到的column "s" does not exist错误,根源是rust-postgres不支持%s这种C风格的参数占位符——它遵循PostgreSQL原生规则,使用$1、$2这类位置标记绑定参数。你的SQL里写了WHERE table_schema=%s,执行时PostgreSQL没识别出这是占位符,反而把%s当成了列名s,因此抛出找不到列的错误。
解决方案
把查询语句中的%s替换为PostgreSQL原生的$1占位符,同时结合你启用的with-serde_json-1特性,可以直接将JSON结果解析为serde_json::Value进行遍历操作。修正后的完整代码如下:
extern crate postgres; extern crate serde_json; use postgres::{Client, NoTls}; use serde_json::Value; fn main() { // 替换为实际数据库连接信息 let db_url = "postgresql://postgres:mypass@localhost/users"; // 连接数据库 let mut client = Client::connect(db_url, NoTls).expect("连接数据库失败"); let schema = "public"; // 修正占位符为PostgreSQL原生的$1 let query = r#" select row_to_json(Tb) as tbls from( SELECT T."table_name", (select json_agg(col) from ( SELECT "column_name", udt_name, is_nullable, data_type, column_default FROM information_schema.columns WHERE table_name = T."table_name" AND column_default NOT LIKE 'nextval%%' ) col ) as cols, (select json_agg(colx) from ( SELECT "column_name", udt_name, is_nullable, data_type, column_default FROM information_schema.columns WHERE table_name = T."table_name" ) colx ) as identifiable_columns, (select json_agg(colr) from ( SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name=T."table_name" ) colr ) as relates FROM information_schema.tables as T WHERE table_schema=$1) Tb; "#; // 执行查询并解析JSON结果 let rows = client.query(query, &[&schema]).expect("执行查询失败"); // 遍历结果并处理JSON for row in rows { let tbl_json: Value = row.get("tbls"); println!("表结构JSON: {:#?}", tbl_json); // 示例:提取表名和列信息 if let Some(table_name) = tbl_json.get("table_name").and_then(Value::as_str) { println!("表名: {}", table_name); } if let Some(cols) = tbl_json.get("cols").and_then(Value::as_array) { println!("列列表:"); for col in cols { println!(" 列名: {}", col.get("column_name").unwrap().as_str().unwrap()); } } } }
补充说明
- 占位符规则:rust-postgres严格遵循PostgreSQL的位置占位符逻辑,
$n对应参数列表中的第n个元素,这里$1对应&[&schema]里的第一个参数。 - JSON解析:启用
with-serde_json-1特性后,可直接通过row.get方法将查询结果中的JSON字段解析为serde_json::Value,方便后续遍历、提取数据。 - 模糊匹配写法:在Rust原始字符串(
r#"..."#)中,%无需额外转义,你写的nextval%%会被PostgreSQL正确识别为nextval%的模糊匹配规则。
内容的提问来源于stack exchange,提问作者alexander
相关产品推荐
相关产品推荐

