基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
隐式引用内联视图重名投影项结果错误
更新时间:2026-05-25 09:11
问题现象
Case 1:
select * from (select 1,1 from dual union select 3,4 from dual);查询结果为:
1,1 3,3正确结果应为:
1,1 3,4Case 2:
select * from (select 1,1 from dual); select * from (select 1,3 from dual);以上查询连续执行后,第二个查询会复用第一个查询的执行计划。第二个查询结果为:
1,1
正确结果应为:
1,3
在业务场景中,经常会将以上查询的结果作为 insert into 的输入。类似执行以下语句。
insert into t1 select * from (select 1,1 from dual union select 3,4 from dual);
插入结果错误,表现形式是: 内联视图中多个重名列插入的结果均使用第一个重名列的结果。
关键诊断信息
触发条件
查询中存在
select * from inline_view的子句。inline_view中,投影项存在重名列。例如select 1,1 ...。这里两个投影表达式的列名是相同的。
事前巡检
巡检 SQL 文本中存在 select * from 的子句。
事后诊断
按照触发条件分析查询是否存在隐式引用重名列的行为。
问题原因
对 select * from inline_view 这样的子句,在解析的时候,如果 inline_view 中投影列的名称相同,SQL 引擎在解析 select * 的时候,会发生错位,将视图投影项中的多个重名列均解析为第一个重名投影列。实际的解析效果可以参考以下案例理解。
select * from (select 1, 1 from dual) v;
以上语句正常解析结果应该是:
select v.s1, v.s2 from (select 1 as s1, 1 as s2 from dual) v;
但实际解析结果却为:
select v.s1, v.s1 from (select 1 as s1, 1 as s2 from dual) v;
单独执行以上语句结果并不会出现错误。但以上语句的执行计划可能被复用。例如以上语句的执行结果如果被下面语句复用的时候。
select * from (select 1, 2 from dual) v;
实际的执行效果就为:
select v.s1, v.s1 from (select 1 as s1, 2 as s2 from dual) v;
上述的执行结果是错误的。它错误的把 s1 的结果填充到了 s2 的位置上。
问题的风险及影响
SQL 执行结果错误。
影响租户
影响 OceanBase 数据库中的 Oracle 租户,对于 SYS 租户和 MySQL 租户无影响。
影响版本
OceanBase 数据库企业版 V3.2.3 GA(20220419)及之后版本、V3.2.4 GA(oceanbase-3.2.4.0-100000072022102819)及之后版本、V4.1.0 GA(oceanbase-4.1.0.0-100001122023040322)及之后版本、V4.2.0 GA(oceanbase-4.2.0.0-100010082023083014)及之后版本、V4.2.1 GA(oceanbase-4.2.1.0-100000182023092722)及之后版本、V4.2.2 GA(oceanbase-4.2.2.0-100000082024011317)及之后版本、V4.3.0(oceanbase-4.3.0.0-100000072024020200)及之后版本。
解决方法
解决方法:
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V3.2.3 BP11(oceanbase-3.2.3.3-111000032024070822)及之后版本、V3.2.4 BP8(oceanbase-3.2.4.8-108000142024041520)及之后版本、V4.2.1 BP8(oceanbase-4.2.1.8-108000052024072217)及之后版本、V4.2.4(oceanbase-4.2.4.0-100000252024070621)及之后版本、V4.3.2 (oceanbase-4.3.2.0-100000442024071321)及之后版本。
如果
select * from引用的内联视图不包含union操作,可以尝试对该 SQL 注入use_plan_cache(none),不共享执行计划。如果
select * from引用的内联视图中包含union操作。只能通过修改 SQL 的方式来避免结果错。
规避方式:
修改 SQL 文本,对重名列给出明确的别名。例如,给定以下 SQL。
select * from (select 1, 2 from dual) v;修改为:
select * from (select 1 as s1, 2 as s2 from dual) v;