简体   繁体   中英

Oracle SQL Query working in 12C but not in 11g

I've a Oracle SQL Query that works fine in 12C, but not in 11g. I've given a similar example below. Please explain if this is a bug/enhancement fixed in 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

Please note that, I've re written a different logic to fix this, but I wanted to know if this is a bug in 11g or an enhancement in 12C.

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

In either database, you could write this as:

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

No subqueries are needed. As pointed out, you do not need the addiitonal level of subqueries. The innermost subquery just returns one row anyway .

Oracle has only allowed correlated references to the direct parent in a subquery -- not to higher level parents. That would seem to argue that your query would not work in any version of Oracle. However, I believe that Oracle 12c does some optimizations before imposing this rule. The documentation alludes to this:

Oracle performs a correlated subquery when a nested subquery references a column from a table referred to a parent statement one level above the subquery. . . . A correlated subquery conceptually is evaluated once for each row processed by the parent statement. However, the optimizer may choose to rewrite the query as a join or use some other technique to formulate a query that is semantically equivalent . Oracle resolves unqualified columns in the subquery by looking in the tables named in the subquery and then in the tables named in the parent statement.

I suspect that this optimization is removing your unnecessary subquery, and hence allowing the query to compile.

The Oracle documentation has always been explicit that correlation is permitted only one level deep (although there is no clear reason for that, and it is against the SQL Standard).

As Solomon Yakobson, one of the gurus there, has explained several times on OTN, in each new version, in sub-version 1 (as in, 10.1, 11.1), correlation at deeper levels worked OK, just like the OP noticed. It used to be "fixed" (the flexibility was taken back) in sub-version 2 (10.2, 11.2). 12.1 had the same "enhancement" (correlation at all levels), and 12.2 did NOT take that away - even though the documentation STILL says correlation is not permitted more than one level down. Especially since such limitations don't exist when we write queries with the WITH clause, it makes zero sense for Oracle to continue with that restriction.

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

Oracle performs a correlated subquery when a nested subquery references a column from a table referred to a parent statement one level above the subquery [...]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM