Skip to content

语义查询能力应该分层承诺:DSL、Semantic SQL、CTE 与小结果二次分析

AI 数据查询很容易陷入一个模糊承诺:

text
用户想怎么问,系统就怎么查。

这句话听起来很强,但工程上几乎不可验证。

企业数据查询不是单一能力。简单筛选、聚合统计、多维透视、跨模型关联、临时结果二次分析、受限 SQL、底层 CTE、导出、图表和自然语言解释,背后是不同的执行边界、权限风险和可审计要求。

如果把这些能力混在一起承诺,用户会自然理解成:

  • 可以写任意 SQL;
  • 可以跨任意表 join;
  • 可以绕过业务模型直接查底层库;
  • 可以对任何中间结果继续分析;
  • 可以导出任意明细;
  • 可以把查询结果当成无条件正确。

这不是生产级 AI 数据访问应该采用的口径。

更稳的方式是把语义查询能力分层:每一层说明能做什么、不能做什么、权限在哪里生效、证据如何保留,以及什么时候应该澄清或拒绝。

为什么要分层承诺

不同查询能力的风险不一样。

一个按月份汇总销售额的查询,和一个跨销售、库存、财务模型做临时结果 join 的查询,不应该使用同样的安全假设。

一个只能引用查询模型字段的 JSON DSL,和一个允许用户写 SQL 片段的接口,也不应该被包装成同一种能力。

能力分层的目标有三个。

第一,让用户知道当前系统到底支持什么。

如果系统只稳定支持查询模型上的筛选、分组、排序和聚合,就应该明确说清楚。不要把它描述成“AI 可以自由分析数据库”。

第二,让开发者知道安全边界在哪里。

字段校验、权限注入、行级切片、结果裁剪和审计证据必须绑定到具体执行层。不能只在高层文案里说“安全可控”。

第三,让后续演进有路径。

DSL、Compose、受限 Semantic SQL、小结果二次分析都可以共存,但它们应该有清晰的适用场景和成熟度标记,而不是一次性混成一个不可控入口。

第一层:Query Model + JSON DSL

最适合作为稳定默认层的,是查询模型加结构化 DSL。

这层的核心特点是:AI 不直接写物理 SQL,而是在查询模型允许的字段、维度、指标和操作范围内提交结构化查询请求。

典型能力包括:

  • 选择查询模型;
  • 引用模型暴露的字段、维度和指标;
  • 设置筛选条件;
  • 设置排序、分页和行数限制;
  • 按维度分组聚合;
  • 使用已定义指标;
  • 使用受控计算字段;
  • 请求透视、小计或基础趋势分析;
  • 返回结构化结果和查询证据。

这一层的优势是治理边界清晰。

字段是否可见,可以在 DSL 校验阶段判断。行级权限和公司边界,可以在编译前注入。指标口径,可以由查询模型定义。底层 SQL 是引擎的编译产物,而不是 AI 的原始输入。

这层适合承诺为生产默认能力。

但它也有边界:

  • 不支持任意 SQL;
  • 不支持任意跨表 join;
  • 不支持引用查询模型外的字段;
  • 不保证能表达所有临时分析需求;
  • 不允许绕过字段和行级权限;
  • 不应该默认支持写回业务数据。

换句话说,这一层不是为了让 AI 更自由,而是为了让 AI 查询可校验、可审计、可复核。

第二层:Compose / 多步骤语义查询

很多业务分析不是一个单查询能完成的。

例如:

  • 先按客户聚合销售额,再筛出 Top 20 客户;
  • 先计算逾期应收,再按客户类型分组;
  • 先查询库存可用量,再结合销售订单需求判断缺口;
  • 先得到每月销售额,再计算环比变化;
  • 先查询两个模型,再做受限匹配和汇总。

这类需求需要多步骤查询计划。

可以把这一层理解为 Compose:系统允许 AI 提交一个由多个受控查询步骤组成的计划,每一步仍然基于查询模型和 DSL 执行。

Compose 的关键不是“让 AI 写复杂脚本”,而是让复杂分析拆成可审计的步骤:

text
step 1: 查询销售模型,按客户聚合销售额
step 2: 对 step 1 结果排序,取 Top 20
step 3: 查询应收模型,按客户聚合未结清金额
step 4: 在受控中间结果上合并客户维度
step 5: 输出客户销售额与应收风险对比

这一层比单查询更强,也更容易出风险。

需要明确的边界包括:

  • 每一步仍然只能访问当前用户可见的查询模型;
  • 中间结果不能自动突破原始权限;
  • 跨模型关联必须有受控 key 和数据规模限制;
  • 中间结果保留时间、可见性和审计记录要清楚;
  • 执行失败时应该返回到具体步骤;
  • 结果解释要引用具体步骤和证据。

Compose 适合用于高阶分析,但不应该被描述成任意脚本执行能力。

它更像受控的数据分析工作流,而不是开放式数据库编程环境。

第三层:底层 CTE 是实现策略,不是用户承诺

CTE、子查询、窗口函数、临时表、物化中间结果,这些都是数据库查询实现里常见的技术。

在语义查询引擎内部,它们很有价值。

例如,引擎可能把一个多步骤语义查询编译成带 CTE 的 SQL;也可能为了性能,把某些中间结果落到临时表;还可能通过窗口函数实现排名、环比或移动平均。

但这不意味着应该对用户承诺:

text
你可以让 AI 任意写 CTE。

底层 CTE 是实现策略,不是安全边界。

如果用户或 AI 可以直接写任意 CTE,系统就重新回到了 raw SQL 的问题:字段权限、行级规则、公司边界、方言差异和审计解释都会变复杂。

更稳妥的表述是:

  • 引擎可以在内部使用 CTE、窗口函数或临时结果优化执行;
  • AI 提交的仍然是受控语义查询请求;
  • 用户看到的是查询模型、步骤、字段、指标和证据;
  • 底层 SQL 可以进入工程审计或调试证据;
  • 不把底层 SQL 表达能力直接暴露成用户自由能力。

这一区分很重要。

否则外部读者会把“引擎内部支持复杂 SQL 生成”理解成“AI 可以随便写 SQL 查业务库”。

第四层:受限 Semantic SQL

SQL 对很多开发者和模型来说都很自然。

因此,在某些场景下,提供受限 Semantic SQL 是合理方向。

但 Semantic SQL 必须和 raw SQL 区分开。

raw SQL 面向物理数据库对象:

sql
select *
from sale_order so
join res_partner rp on rp.id = so.partner_id

Semantic SQL 应该面向语义模型对象:

sql
select customerRegion, sum(confirmedSalesAmount)
from sales_order_analysis
where orderDate between '2026-01-01' and '2026-03-31'
group by customerRegion

这里的 sales_order_analysis 不是物理表,而是查询模型。confirmedSalesAmount 不是随便猜的列,而是模型定义过的指标。

受限 Semantic SQL 如果要进入生产,需要满足几个条件:

  • FROM 只能引用可见查询模型;
  • SELECTWHEREGROUP BYORDER BY 只能引用可见字段和指标;
  • 禁止或限制 DDL、DML、函数、子查询、union、任意表达式等高风险语法;
  • SQL 必须先解析成 AST;
  • AST 必须通过语义层校验;
  • 校验后再转换为内部 DSL 或执行计划;
  • 执行仍然注入权限和公司边界;
  • 审计记录保留原始 Semantic SQL、AST 摘要、DSL 和执行证据。

这样,Semantic SQL 才是语义查询的上层表达,而不是绕过语义层的后门。

它的价值在于降低表达复杂查询的门槛,尤其对熟悉 SQL 的开发者和模型友好。但它的边界必须清楚:不是物理数据库 SQL,不是任意 SQL,也不是权限绕过入口。

第五层:小结果二次分析

还有一类需求很常见:先查出一个小结果集,再继续分析。

例如:

  • 先得到 Top 20 客户,再对这 20 个客户做风险分组;
  • 先按产品聚合销售额,再计算占比;
  • 先查询逾期应收列表,再按账龄区间重新分桶;
  • 先得到一个聚合表,再生成图表或摘要。

这类“小结果二次分析”可以提升体验,但也需要边界。

小结果不是无权限数据。

如果中间结果包含敏感字段,二次分析仍然要受字段可见性和导出策略约束。如果中间结果来自某个公司上下文,后续分析不能悄悄扩展到其他公司。如果中间结果被脱敏或截断,最终答案必须说明。

更可靠的设计是:

  • 只允许对已授权、已返回的小结果进行二次分析;
  • 限制结果行数、列数和保留时间;
  • 区分聚合结果和明细结果;
  • 不允许二次分析重新访问底层数据库;
  • 需要跨模型补充数据时,必须重新发起受控查询;
  • 二次分析过程也要进入 provenance。

小结果二次分析适合处理排序、占比、简单派生、格式转换、图表准备和摘要生成。

它不应该被扩展成一个隐形的数据湖或无限制临时数据库。

能力分层可以如何对外表达

对外文档和产品说明里,建议把能力分成类似下面的层级。

层级能力适合承诺关键边界
L1Query Model + JSON DSL稳定默认能力不暴露任意 SQL;只查可见模型和字段
L2Compose 多步骤语义查询受控高阶能力每一步可审计;中间结果不突破权限
L3引擎内部 CTE / 窗口函数实现细节不等同于用户可写任意 CTE
L4受限 Semantic SQL可选 / 演进能力面向语义模型,必须 AST 校验和权限注入
L5小结果二次分析辅助分析能力只处理已授权小结果,不重新访问底层库

这类分层能减少误解。

用户知道什么是稳定能力,什么是受控能力,什么是内部实现,什么是后续方向。开发者也能据此设计工具、测试、审计和错误处理。

和权限治理的关系

能力越高阶,越不能放松权限。

很多系统的问题不是没有权限,而是权限只在最简单路径上生效。一旦进入跨模型分析、临时结果、SQL 片段或二次处理,权限就变得模糊。

一个一致的原则是:

text
权限应该绑定到语义对象和执行步骤,而不是绑定到某一种入口形式。

无论请求来自自然语言、JSON DSL、Semantic SQL,还是 Compose 步骤,最终都应该落到同一套语义模型、字段可见性、行级切片、公司上下文和审计记录上。

如果某条能力路径绕过了这套执行边界,它就不应该进入生产默认能力。

对 Odoo / ERP 场景的含义

在 Odoo / ERP 场景里,能力分层尤其重要。

Odoo 数据模型复杂,模块多,二开多,权限规则也多。用户的问题往往跨销售、采购、库存、会计和客户管理。直接承诺“AI 可以自由分析 Odoo 数据库”,会让实施风险非常高。

更合理的表述是:

  • 当前稳定能力:基于已建模的 Odoo 查询模型做筛选、聚合、排序、分页和图表数据准备;
  • 受控能力:在多个可见查询模型之间做分步骤分析,并保留每一步证据;
  • 不默认承诺:让 AI 直接写 PostgreSQL SQL 查询 Odoo 裸表;
  • 不承诺:绕过 Odoo 用户权限、record rules、多公司边界或字段可见性;
  • 后续方向:受限 Semantic SQL 或小结果二次分析,但仍然经过语义层校验。

这比一句“支持 AI 查询 Odoo 数据”更啰嗦,但也更可信。

企业客户和实施团队真正需要的是可落地边界,而不是泛化承诺。

结论

语义查询能力应该分层承诺。

Query Model + JSON DSL 适合作为稳定默认层,因为它最容易做字段校验、权限注入、业务口径控制和查询证据记录。

Compose 可以支持更复杂的多步骤分析,但必须保证每一步仍在模型和权限边界内。

CTE、窗口函数和临时表可以作为引擎内部实现策略,不应该被直接包装成“AI 可写任意 SQL”。

受限 Semantic SQL 可以作为演进方向,但必须面向语义模型、经过 AST 校验,并转换到受治理执行计划。

小结果二次分析可以提升体验,但只能处理已授权、受限制、可审计的结果集。

Foggy Data MCP / Foggy Odoo Bridge 的技术口径应该保持这种分层:强调受治理的语义查询能力,而不是承诺任意 SQL、任意跨表分析、任意导出或绕过宿主系统权限。这样对开发者、架构师和 ERP 实施团队都更清楚,也更容易进入真实生产环境。