【问题标题】:Oracle SQL Query working in 12C but not in 11gOracle SQL 查询在 12C 中工作,但在 11g 中不工作
【发布时间】:2026-01-14 21:20:05
【问题描述】:

我有一个在 12C 中可以正常工作的 Oracle SQL 查询,但在 11g 中却不行。我在下面给出了一个类似的例子。请说明这是否是 12C 中修复的错误/增强功能。

CREATE TABLE MSI_OWNER.VINOTH_TEST1
(
  COL1  VARCHAR2(100 BYTE),
  SAL   NUMBER,
  YEAR  NUMBER
)

Insert into MSI_OWNER.VINOTH_TEST1   (COL1, SAL, YEAR) Values   ('Vinoth', 100, 1);
Insert into MSI_OWNER.VINOTH_TEST1   (COL1, SAL, YEAR) Values   ('Vinoth', 100, 2);
COMMIT;

  SELECT col1,
         (SELECT MAX (its)
            FROM (SELECT MAX (year) its
                    FROM vinoth_test1 x
                   WHERE x.col1 = a.col1))
            max_year,
         sal
    FROM vinoth_test1 a
GROUP BY col1, sal

请注意,我已经重新编写了一个不同的逻辑来解决这个问题,但我想知道这是 11g 中的错误还是 12C 中的增强。

Error in 11g: ORA-00904: "A"."COL1": invalid identifier

【问题讨论】:

  • 11版有什么问题?
  • 您在 Oracle 11 中遇到的错误是什么?
  • ORA-00904: "A"."COL1": 无效标识符。我在 11g 中遇到了这个错误。在 12C 中,它执行得很好并为我提供了正确的结果。

标签: sql oracle oracle11g oracle12c


【解决方案1】:

在任一数据库中,您都可以这样写:

select col1, sal,
       max(max(year)) over (partition by col1)
from vinoth_test1
group by col1, sal;

不需要子查询。正如所指出的,您不需要额外级别的子查询。最里面的子查询只返回一行反正

Oracle 只允许在子查询中对直接父级进行关联引用,而不是对更高级别的父级进行关联引用。这似乎表明您的查询在任何版本的 Oracle 中都不起作用。但是,我相信 Oracle 12c 在实施此规则之前做了一些优化。 documentation 暗示了这一点:

当嵌套子查询时,Oracle 会执行相关子查询 引用表中的列引用父语句一个 高于子查询的级别。 . . .一种 相关子查询在概念上每行评估一次 由父语句处理。但是,优化器可能会选择 将查询重写为连接或使用其他技术 制定一个语义等价的查询。甲骨文解决 通过查看名为 in 的表,子查询中的非限定列 子查询,然后在父语句中命名的表中。

我怀疑这种优化正在删除您不必要的子查询,从而允许编译查询。

【讨论】:

【解决方案2】:

Oracle 文档一直明确表示只允许关联深度为一个级别(尽管没有明确的理由,而且它违反了 SQL 标准)。

正如那里的一位大师所罗门·雅科布森(Solomon Yakobson)在 OTN 上多次解释的那样,在每个新版本中,在子版本 1(如 10.1、11.1)中,更深层次的相关性工作正常,就像 OP注意到。它曾经在子版本 2(10.2、11.2)中被“修复”(灵活性被收回)。 12.1 具有相同的“增强”(所有级别的相关性),而 12.2 并没有消除这一点 - 尽管文档仍然说相关性不允许超过一个级别。尤其是当我们使用 WITH 子句编写查询时,这些限制不存在,因此 Oracle 继续使用该限制是零意义的。

https://docs.oracle.com/database/122/SQLRF/Using-Subqueries.htm#SQLRF52357

当嵌套子查询引用表中的列时,Oracle 执行相关子查询,该列引用了子查询之上一级的父语句 [...]

【讨论】:

  • 是否有某种解决方法来解决这个限制?我面临着类似的问题:*.com/q/61319654/6859002
  • @MigsIsip - 在许多情况下,您可以使用 with 子句重写您的查询。
  • 我尝试过类似的方法,但似乎无法解决。你能看看吗?谢谢