表或视图不存在 - Oracle抱怨逗号而不是实际的表或视图名称

4

我以前从未见过这种情况... 我有一个查询,开始于:

with q1 as
     (select a.V_ID, a.D_ID, a.C_ID,
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_val,
               a.C_val
       from ab_a_table a
       where a.C_ID =  '00000003' -- '00000007' --  test values
             and a.B_VAL = '6010001'
             and a.Q = '11234567')
select case
           when ... /* rest of query omitted */

当我尝试运行此代码时,Oracle抱怨一个“表或视图不存在”的问题。但是,它在第3行上突出显示逗号,而不是实际的表/视图名称:
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_VAL,
                                                                  *
ERROR at line 3:
ORA-00942: table or view does not exist
我省略了其余的查询,因为它非常长和复杂 - 如果需要,我会进行清理并发布它 - 现在我只想说,当我添加第三个引用q1的子查询时,才出现这个错误。 实际上,似乎我可以删除其中任何一个子查询,整个查询都将执行(尽管结果不正确),因此感觉像是我遇到了某种Oracle错误,而不是纯SQL错误。有趣的是,当我将q1体作为独立查询运行时,它没有任何问题。只有当我运行整个查询时,它才抱怨q1中case后面的逗号。
有没有人经历过这种情况?
(使用Oracle 10g)。
编辑:尝试添加AS关键字。现在的结果如下:
               case when a.perc_fault > 0 THEN 'Y' ELSE 'N' end AS L_VAL, a.C_VAL
                                                                     *
ERROR at line 3:
ORA-00942: table or view does not exist
看起来星号位于相同的位置,但在V下面,因为单词L_VAL已向右移动了3个字符。非常奇怪...

这可能有点冒险,但请尝试将问题行更改为"case when a.percent > 0 THEN 'Y' ELSE 'N' end AS L_VAL" - 换句话说,添加"AS"关键字。 - Bob Jarvis - Слава Україні
1
显然错误不在公共表达式之内,因此您应该发布完整的语句。我强烈认为高亮显示只是指向错误位置的错误工具 - 因为“Oracle”不会进行错误高亮显示。 - user330315
1
@FrustratedWithFormsDesigner:你使用的是哪个补丁级别?在10.2.0.4补丁集中有一个与ORA-00942和WITH子句相关的错误修复:5130732。它有点模糊,但看起来优化器出了问题,所以我可以相信添加或删除一个子查询可能会有所不同。(此外,错误报告中的示例也指向第3行)。 - Alex Poole
1
@FrustratedWithFormsDesigner:Metalink的注释和错误报告没有提供任何解决方法。你可以尝试一些提示,但我不知道什么可能有帮助——我害怕只能试错了。 (PUSH_SUBQ、UNNEST或NO_UNNEST也许可以……)。否则,你将不得不重新设计查询以避免连接。唯一想到的其他事情是创建一个返回refcursor的函数,并在其中使用游标替换子查询。无论你做什么,都可能会对性能产生影响。 - Alex Poole
2
如果问题是Alan Poole所描述的WITH子句错误,请尝试将WITH子句更改为内联视图。或者创建一个实际的视图。 - redcayuga
显示剩余5条评论
2个回答

0

我不确定我是否遇到了Oracle bug 5130732,但感觉很像。无论如何,我已经重写了查询语句:

select case ... 
from
    (select ...
     from (select a.V_ID, a.D_ID, a.C_ID,
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_val,
               a.C_val
       from ab_a_table a
       where a.C_ID =  '00000003' -- '00000007' --  test values
             and a.B_VAL = '6010001'
             and a.Q = '11234567') q1,  <other tables>
    where ...) subquery1,
    (select ...
     from (select a.V_ID, a.D_ID, a.C_ID,
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_val,
               a.C_val
       from ab_a_table a
       where a.C_ID =  '00000003' -- '00000007' --  test values
             and a.B_VAL = '6010001'
             and a.Q = '11234567') q1,  <other tables>
    where ...) subquery2,
    (select ...
     from (select a.V_ID, a.D_ID, a.C_ID,
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_val,
               a.C_val
       from ab_a_table a
       where a.C_ID =  '00000003' -- '00000007' --  test values
             and a.B_VAL = '6010001'
             and a.Q = '11234567') q1,  <other tables>
    where ...) subquery3, <other tables>
where....

是的,我在每个使用了q1的子查询中都包含了一份副本,现在一切都正常了。一个真正的视图也可以工作,但这样做更容易(政治上来说是这样的 - 不需要在分析需要完成的环境中提交代码推广请求,不需要关于数据库中新增对象的会议等等...)


更新

现在,我已经将查询添加到我的PL/SQL脚本中,Oracle给出了ORA-00600 [qcscpqbTxt],[600]的错误提示,这似乎与Oracle bug#5765958有关...* 叹气 *...有人能提供一种解决方法吗?我没有metalink访问权限(好吧,如果通过DBA,我可能会有,只要这些信息可以引起他们的注意)。


1
你的数据库管理员可能已经知道了ORACLE 600错误,因为它会在告警日志中出现。5765968似乎是指ANSI连接和/或绑定变量;猜测你的PL / SQL版本将使用变量而不是硬编码值。还有关于5532110的引用,但看不到任何详细信息。也没有提到解决方法。目前还不清楚是否仍然是子查询导致问题,但我认为这很可能。如果只是希望优化器不要尝试过于聪明,请考虑在你的PL / SQL中使用返回游标引用的本地函数。您是否在此处尝试了提示? - Alex Poole
@Alex Poole:今天早些时候,数据库管理员给我发送了错误的跟踪文件。他说他可能会联系Oracle,但我打算首先尝试将代码与查询分开来解决问题。 - FrustratedWithFormsDesigner

0
假设您遇到了Oracle的错误并且无法修补数据库,您可以尝试将子查询移动到函数中。不完全确定这是否有效,并且假定您的PL/SQL版本在包中,或者有一个可用的包可以添加函数:
在包规范中:
type q1_rec is record(
    d_id ab_a_table.v_id%TYPE,
    v_id ab_a_table.d_id%TYPE,
    c_id ab_a_table.c_id%TYPE,
    l_val char(1),
    c_val ab_a_table.c_val%TYPE);
type q1_arr is varray(9999); -- assuming you can pick a max size
function q1 return q1_arr pipelined;
pragma restrict_references(q1, wnds);

在包体中:
function q1 return q1_arr pipelined is
    cursor c is
        select a.V_ID, a.D_ID, a.C_ID,
               case when a.percent > 0 THEN 'Y' ELSE 'N' end L_val,
               a.C_val
       from ab_a_table a
       where a.C_ID =  '00000003' -- '00000007' --  test values
             and a.B_VAL = '6010001'
             and a.Q = '11234567');
begin
    for r in c loop
        pipe row(r);
    end loop;
end;

然后在您的主查询中,使用 table(q1()) 替换子查询。

使用 ref cursor 或嵌套表可能会更整洁,但需要在包之外构建一个表类型,我猜您想避免根据有关使用视图的额外对象评论。


我可能会朝这个方向前进,但需要一些时间来弄清楚如何拆分事物... - FrustratedWithFormsDesigner
1
我的代码不完全相同,但思路类似——我将巨大的查询子查询分成了3个游标,然后将整个过程包装在一个函数中,使用约十几行代码控制要运行哪个查询。虽然有些丑陋,但它能够正常工作,并且由于该函数存在于我的脚本中,我甚至不需要编译任何包! :) - FrustratedWithFormsDesigner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接