简体   繁体   中英

error after migration from oracle 11g to 19c

could anyone explain how the below select works:

select A.B.Column1 Col1
FROM TableA A LEFT JOIN TableB B
ON B.id=A.id;

What does A.B.Column1 mean? After migration from oracle 11g to 19c my package throws an error:

PL/SQL: ORA-00904: "A"."B"."Col1":
         invalid identifier

It shouldn't have worked in 11g either, but ANSI syntax sometimes has issues - particularly in older versions - and you happened to hit a confusing, but fairly benign one.

In this case the parser/optimiser is apparently ignoring what could be, but isn't, a reference to the table's schema. That seems to be happening during the internal translation of the ANSI syntax to native Oracle syntax. It doesn't matter what that first part is; you've shown A matching another table's alias, but that's a coincidence; both of these work, at least in 11.2.0.2, even though Z is never mentioned anywhere else:

select A.B.Column1 Col1
FROM TableA A LEFT JOIN TableB B
ON B.id=A.id;

select Z.B.Column1 Col1
FROM TableA A LEFT JOIN TableB B
ON B.id=A.id;

I've said it's an ANSI issue because (a) it errors with an inner join as you mentioned, and (b) it also errors with old-fashioned outer-join syntax:

select A.B.Column1 Col1
FROM TableA A, TableB B
WHERE B.id = A.id (+);

ORA-00904: "A"."B"."COLUMN1": invalid identifier

SQL Fiddle demo

There isn't much point worrying about how it worked before, or (for example) raising a service request against such an old version. It's a bug in your old version of Oracle, and it's fixed now. It shouldn't have worked, and since it - correctly - doesn't work in 19c, you have to fix it, by removing the stray A. .

The SQL is invalid.

Knowing this there are only 2 possibilities:

  1. 11g likewise raised an error; or
  2. 11g has a "more relaxed" error tolerance than 19c and has made an assumption as to whether A or B and applied the selection in your output.

Either way, given that it is your package, the solution should be fairly trivial:

  1. If you know which table you are expecting the result to be from then remove the incorrect table's reference from the alias

  2. if A has "Column1" and B doesn't then remove "B." from the alias

  3. if B has "Column1" and A doesn't then remove "A." from the alias

  4. If both A and B have "Column1" then find an 11g database an create a dummy query where A.id = B.id and A.Column1 differs in value from B.Column1. Then run the query and if the result is A.Column1 value then remove "B." from the alias but if the result is B.Column1, remove "A." from the alias.

  5. if you are trying to implement the logic "if B.Column1 is null then return the value of A.Column1 otherwise return the value of B.Column1", then correct your SQL to read something like:

    select case
             when B.Column1 is null then
             A.Column1
           else
             B.Column1
           end as Col1
    from TableA A left join TableB B
    on B.id = A.id;

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