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

如何在X++中构建带where子句及跨表OR条件的Query查询

X++ 跨多关联表实现跨字段OR模糊匹配方案

你之前两种写法不生效的核心原因:

  • 跨数据源单独调用addQueryFilter/addRange添加的条件,默认会用AND逻辑连接,只有同个数据源下、绑定同个字段的多个Range值才会自动拼成OR条件,跨表场景不会自动生成OR逻辑
  • 你写的addRange版本存在逻辑错误:每调用一次addRange就会生成一个独立的新Range对象,你反复给qbr变量赋值会覆盖之前的Range引用,最后value()只作用在最后一个绑定到TABLE3.c字段的Range上,自然生成的SQL不符合预期。

下面是两种可直接落地的实现方式,生成的SQL和你给出的预期效果完全一致:


方案1:根数据源绑定全表达式Range(兼容性最好,最常用)

核心思路是把所有跨表OR条件拼成一个完整的合法表达式,绑定到最外层根数据源(也就是你的TABLE1)的Range上即可,不需要给子表单独加筛选条件。注意提前配置好子表的关联关系和连接模式。
示例代码:

Query                  query = new Query();
QueryBuildDataSource   tab1, tab2, tab3;
QueryBuildRange        crossTableOrRange;
str                    searchValue = 'F1';

// 初始化主表数据源
tab1 = query.addDataSource(tableNum(TABLE1), 'tab1');

// 配置左外连接的子表2,指定关联字段
tab2 = tab1.addDataSource(tableNum(TABLE2), 'tab2');
tab2.joinMode(JoinMode::LeftOuter);
tab2.addLink(fieldNum(TABLE1, x), fieldNum(TABLE2, x));

// 配置左外连接的子表3,指定关联字段
tab3 = tab1.addDataSource(tableNum(TABLE3), 'tab3');
tab3.joinMode(JoinMode::LeftOuter);
tab3.addLink(fieldNum(TABLE1, x), fieldNum(TABLE3, x));

// 绑定跨表OR条件到主表的Range上,这里选RecId做占位绑定字段即可,不影响条件逻辑
crossTableOrRange = tab1.addRange(fieldNum(TABLE1, RecId));
crossTableOrRange.value(
    strFmt(
        '(%1.%2 LIKE "*%3*" || %1.%4 LIKE "*%3*" || %5.%6 LIKE "*%3*" || %7.%8 LIKE "*%3*")',
        tab1.name(),          // 主表数据源别名
        fieldStr(TABLE1, a),
        searchValue,
        fieldStr(TABLE1, aa),
        tab2.name(),          // 子表2数据源别名
        fieldStr(TABLE2, b),
        tab3.name(),          // 子表3数据源别名
        fieldStr(TABLE3, c)
    )
);

关键注意点:

  • X++ Query语法中模糊匹配的通配符是*,不是SQL原生的%,Query执行时会自动把*转成对应数据库的通配符,直接写%会被当成普通字符匹配
  • 逻辑或写||、逻辑与写&&,不要直接写SQL的OR/AND,避免跨数据库兼容问题
  • 调用数据源的name()方法取别名,比硬编码'tab1'这类字符串更稳妥,后续调整数据源别名不需要修改条件表达式

你提到的dirpartytable三表关联的实际业务场景,直接替换对应表名、字段名、关联关系、搜索值即可套用这个模板。


方案2:QueryFilter绑定全局表达式(适合固定全局筛选场景)

如果是给已有Query追加全局筛选条件,或者用AOT Query做动态开发,可以直接把完整的跨表OR表达式作为QueryFilter的值,绑定到主表数据源即可,效果和方案1一致:

QueryFilter crossFilter = query.addQueryFilter(tab1, fieldStr(TABLE1, RecId));
crossFilter.value(strFmt(
    '(%1.%2 LIKE "*%3*" || %1.%4 LIKE "*%3*" || %5.%6 LIKE "*%3*" || %7.%8 LIKE "*%3*")',
    tab1.name(), fieldStr(TABLE1, a), searchValue, fieldStr(TABLE1, aa),
    tab2.name(), fieldStr(TABLE2, b),
    tab3.name(), fieldStr(TABLE3, c)
));

这个写法生成的筛选条件会固定放在SQL的WHERE最外层,不会随JOIN结构下沉到ON子句,适合不随查询结构变化的固定筛选规则。


避坑提示

  • 不要跨数据源单独添加同值的Range/Filter期待自动拼OR,只有同个数据源绑定同个字段的多个Range值才会自动生成OR逻辑
  • 不要反复覆盖同一个Range变量后再赋值,每个独立条件对应一个独立的Range/Filter对象,跨表OR逻辑必须写在同一个表达式里
  • 不要在Query表达式里直接写原生SQL语法,必须用X++ Query支持的语法规则,否则会被解析器转义导致查询结果错误

内容的提问来源于stack exchange,提问作者devSL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:45:38