You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 13:53:26