简体   繁体   English

从 oracle 11g 迁移到 19c 后出现错误

[英]error after migration from oracle 11g to 19c

could anyone explain how the below select works:谁能解释下面的 select 是如何工作的:

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

What does A.B.Column1 mean? A.B.Column1是什么意思? After migration from oracle 11g to 19c my package throws an error:从 oracle 11g 迁移到 19c 后,我的 package 会引发错误:

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.它也不应该在 11g 中工作,但是 ANSI 语法有时会出现问题 - 特别是在旧版本中 - 你碰巧遇到了一个令人困惑但相当温和的问题。

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.这似乎发生在将 ANSI 语法内部转换为本地 Oracle 语法的过程中。 It doesn't matter what that first part is;第一部分是什么并不重要。 you've shown A matching another table's alias, but that's a coincidence;您显示A与另一个表的别名匹配,但这是巧合; both of these work, at least in 11.2.0.2, even though Z is never mentioned anywhere else:这两项工作,至少在 11.2.0.2 中,即使Z从未在其他任何地方提及:

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:我已经说过这是一个 ANSI 问题,因为(a)它与您提到的内部连接错误,并且(b)它也与老式的外部连接语法错误:

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 SQL 小提琴演示

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.这是您的旧版本 Oracle 中的错误,现在已修复。 It shouldn't have worked, and since it - correctly - doesn't work in 19c, you have to fix it, by removing the stray A. .不应该起作用,并且由于它 - 正确 - 在 19c 中不起作用,因此您必须通过移除杂散A.来修复它。

The SQL is invalid. SQL 无效。

Knowing this there are only 2 possibilities:知道这一点只有两种可能性:

  1. 11g likewise raised an error; 11g 同样引发了错误; 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. 11g 比 19c 具有“更宽松”的容错性,并假设 A 或 B 并在 output 中应用了选择。

Either way, given that it is your package, the solution should be fairly trivial:无论哪种方式,鉴于它是您的 package,解决方案应该相当简单:

  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."如果 A 有“Column1”而 B 没有,则删除“B”。 from the alias来自别名

  3. if B has "Column1" and A doesn't then remove "A."如果 B 有“Column1”而 A 没有,则删除“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.如果 A 和 B 都有“Column1”,则找到一个 11g 数据库并创建一个虚拟查询,其中 A.id = B.id 且 A.Column1 的值与 B.Column1 不同。 Then run the query and if the result is A.Column1 value then remove "B."然后运行查询,如果结果是 A.Column1 值,则删除“B”。 from the alias but if the result is B.Column1, remove "A."来自别名,但如果结果是 B.Column1,则删除“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:如果您尝试实现逻辑“如果 B.Column1 是 null,则返回 A.Column1 的值,否则返回 B.Column1 的值”,然后更正您的 SQL 以读取如下内容:

    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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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