如何在SurrealQL查询中为关系使用参数替代硬编码?
问题:如何将EdgeDB查询中的关联类型设为参数而非硬编码?
原查询代码可正常运行,但希望将->player->member中的player和member替换为参数,而非硬编码。尝试过type::table($member)等方式未成功,不想用format!拼接SQL(存在注入风险且不符合最佳实践),求正确实现方式。
原代码:
let sql = "SELECT *, (SELECT volledige_naam, id FROM ->player->member) as playing FROM type::thing($tb, $id);"; let vars: BTreeMap<String, Value> = map![ "tb".into() => record_id.tb.to_owned().into(), "id".into() => record_id.id.to_owned().into(), ]; let ress = db.ds.execute(&sql, &db.ses, Some(vars)).await?;
解决方案
EdgeDB的参数化查询仅支持值参数,无法直接参数化schema元素(如链接名、表名),但可以通过以下两种合规方式实现需求:
1. 使用EdgeQL动态函数实现
借助std::get_link动态获取关联链接,结合type::table指定目标表,修改后的查询如下:
let sql = "SELECT *, (SELECT volledige_naam, id FROM std::get_link(type::thing($tb, $id), $link_name) JOIN type::table($table_name) ON TRUE) as playing FROM type::thing($tb, $id);"; let vars: BTreeMap<String, Value> = map![ "tb".into() => record_id.tb.to_owned().into(), "id".into() => record_id.id.to_owned().into(), "link_name".into() => "player".into(), // 动态传入链接名 "table_name".into() => "member".into(), // 动态传入表名 ]; let ress = db.ds.execute(&sql, &db.ses, Some(vars)).await?;
std::get_link用于从指定对象上获取指定名称的关联链接type::table($table_name)动态定位要查询的表- 此方式仍保持参数化查询的安全性,不会引入注入风险
2. 使用edgedb-rust查询构建器
如果使用edgedb-rust的查询构建器,可以通过代码动态构建查询结构,完全规避硬编码:
use edgedb_query_builder::*; use uuid::Uuid; // 定义与查询结果匹配的结构体 #[derive(Queryable)] struct PlayingMember { volledige_naam: String, id: Uuid, } #[derive(Queryable)] struct QueryResult { // 这里添加原表的所有字段 playing: Vec<PlayingMember>, } // 动态传入链接名和表名 let link_name = "player"; let table_name = "member"; let query = select(type::thing(record_id.tb, record_id.id)) .with("playing", select( get_link(type::thing(record_id.tb, record_id.id), link_name) .join(type::table(table_name)) .project((field("volledige_naam"), field("id"))) )) .into::<QueryResult>(); let ress = query.execute(&db.ses).await?;
- 查询构建器会自动生成安全的EdgeQL语句,无需手动拼接字符串
- 支持完全动态的schema元素指定,同时保留类型安全
注意事项
- 绝对禁止使用
format!拼接SQL字符串,这会严重引入SQL注入风险,尤其是当参数来自不可信来源时 - 使用动态函数时,建议提前校验传入的链接名和表名是否为合法的schema元素,避免查询报错
内容的提问来源于stack exchange,提问作者jan winsemius
相关产品推荐
相关产品推荐

