SQL相关子查询

时间:2017-02-12 09:08:41

标签: sql oracle correlated-subquery

我正在尝试执行此查询但是正在获取ORA-00904:" QM"。" MDL_MDL_ID":无效的标识符。更令我困惑的是主查询有两个子查询,只有where子句不同。但是,第一个查询运行正常,但第二个查询得到错误。以下是查询。

select (
        select make_description
        from make_colours@dblink1
        where makc_id = (
                select makc_makc_id
                from model_colours@dblink1
                where to_char(mdc_id) = md.allocate_vehicle_colour_id
                )
        ) as colour,
    (
        select make_description
        from make_colours@dblink1
        where makc_id = (
                select makc_makc_id
                from model_colours@dblink1
                where mdl_mdl_id = qm.mdl_mdl_id
                )
        ) as vehicle_colour
from schema1.web_order wo,
    schema1.tot_order tot,
    suppliers@dblink1 sp,
    external_accounts@dblink1 ea,
    schema1.location_contact_detail lcd,
    quotation_models@dblink1 qm,
    schema1.manage_delivery md
where wo.reference_id = tot.reference_id
    and sp.ea_c_id = ea.c_id
    and sp.ea_account_type = ea.account_type
    and sp.ea_account_code = ea.account_code
    and lcd.delivery_det_id = tot.delivery_detail_id
    and sp.sup_id = tot.dealer_id
    and wo.qmd_id = qm.qmd_id
    and wo.reference_id = md.web_reference_id(+)
    and supplier_category = 'dealer'
    and wo.order_type = 'tot'
    and trunc(wo.confirmdeliverydate - 3) = trunc(sysdate)

1 个答案:

答案 0 :(得分:0)

Oracle通常不会在嵌套子查询中识别多个级别的表别名(或其他任何内容); from the documentation

  

当嵌套子查询从引用父子语句的表引用子列时,Oracle执行相关子查询。 [...]对于父语句处理的每一行,概念上对相关子查询进行一次计算。

注意一个级别'部分。因此,在嵌套子查询中,您的qm别名无法被识别,因为它距离qm别名的定义两个级别。 (如果您没有别名,原始表名也会发生同样的事情 - 它不是专门用于别名)。

当您将查询修改为只有select qm.mdl_mdl_id as Vehicle_colour - 或其有效版本(可能是(select qm.mdl_mdl_id from dual) as Vehicle_colour)时 - 您删除了嵌套,qm现在只有一个等级它在查询主体中的定义,因此得到了认可。

您在第一个嵌套子查询中对md的引用可能也未被识别,但解析器往往会向后工作,因此它会看到qm问题第一;尽管查询重写可能会使其有效:

  

但是,优化器可以选择将查询重写为连接,或者使用其他技术来制定语义上等效的查询。

您还可以添加提示以鼓励这样做,但最好不要依赖它。

但是您不需要嵌套子查询,您可以在每个顶级子查询中加入:

select (
        select mc2.make_description
        from model_colours@dblink1 mc1,
            make_colours@dblink1 mc2  
        where mc2.makc_id = mc1.makc_makc_id
        and to_char(mc1.mdc_id) = md.allocate_vehicle_colour_id
    ) as colour,
    (
        select mc2.make_description
        from model_colours@dblink1 mc1,
            make_colours@dblink1 mc2
        where mc2.makc_id = mc1.makc_makc_id
        and mc1.mdl_mdl_id = qm.mdl_mdl_id
    ) as vehicle_colour
from schema1.web_order wo,
...

我坚持使用旧式连接语法来匹配主查询,但您应该考虑使用现代ANSI连接语法重写整个事物。 (我还删除了提到的流氓逗号@Serg,但在发布问题时你可能只是遗漏了真实选择列表中的其他列。)

您可以通过连接主查询中的make和model颜色表来完全避免子查询,两次处理单独的过滤条件,或者一次使用列表达式中的一些逻辑。虽然一步一步......