You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/SQL存储过程用WITH子句出现ORA-00904无效标识符错误

PL/SQL存储过程中WITH子句报错ORA-00904的解决

问题现象

在PL/SQL存储过程中使用WITH子句获取数据时,出现以下错误:

Error(550,37): PL/SQL: ORA-00904: "Q2_DATA"."AR_LENGTH": invalid identifier

原始查询语句

WITH    
    q1_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( SELECT   rj_span_id AS SPAN_ID,
                  rj_maintenance_zone_code AS maint_zone_code,
                  Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS NE_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology NOT LIKE '%AERIAL%'
                           AND      rj_construction_methodology NOT LIKE '%CLAMP%'
                           OR       rj_construction_methodology IS NULL THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS UG_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology LIKE '%AERIAL%'
                           OR       rj_construction_methodology LIKE '%CLAMP%' THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS AR_LENGTH
         FROM     ne.mv_span@ne
         WHERE    Trim(rj_span_id) = PSPAN_ID
         AND      inventory_status_code = 'IPL'
         AND      NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9', 'i')
         AND      rj_maintenance_zone_code = PMAINTZONECODE
         GROUP BY rj_span_id,
                  rj_maintenance_zone_code
        ), 
    q2_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( 
        SELECT span_id as SPAN_ID,
              maintenancezonecode       AS MAINT_ZONE_CODE,
              maint_zone_ne_span_length AS NE_LENGTH,
              fsa_ug                    AS UG_LENGTH,
              fsa_aerial                AS AR_LENGTH
       FROM   tbl_fiber_inv_jobs
       WHERE  span_id = PSPAN_ID
        )
SELECT     
            q1.SPAN_ID, q1.MAINT_ZONE_CODE, 
            q1_data.NE_LENGTH - Nvl(q2_data.NE_LENGTH, 0) as NE_LENGTH, 
            q1_data.UG_LENGTH - Nvl(q2_data.UG_LENGTH, 0) as UG_LENGTH,
            q1_data.AR_LENGTH - Nvl(q2_data.AR_LENGTH, 0) as AR_LENGTH
            
FROM        q1_data q1
LEFT JOIN   q2_data q2  ON(q2.SPAN_ID = q1.SPAN_ID)
ORDER BY    q1.SPAN_ID, q1.MAINT_ZONE_CODE;

更新:完整存储过程

PROCEDURE Get_spaninfo_by_span_mz_new (pspan_id       IN NVARCHAR2,
                                         pmaintzonecode IN VARCHAR2,
                                         pspantype      IN NVARCHAR2,
                                         pspaninfodata  OUT SYS_REFCURSOR)
  AS
  VAR_PARTIAL_QTY NUMBER;
  
  
  BEGIN
  
  VAR_PARTIAL_QTY :=0;
  
  SELECT COUNT(JOB_ID) INTO  VAR_PARTIAL_QTY from tbl_fiber_inv_jobs 
        where span_id = PSPAN_ID
AND JOB_FLAG = 1;
  
      IF pspantype = 'INTERCITY' AND  VAR_PARTIAL_QTY = 0 
         AND Length(pspan_id) = 21 THEN
        BEGIN
            OPEN pspaninfodata FOR
              SELECT rj_span_id AS span_id,
                     rj_maintenance_zone_code                        AS
                     maint_zone_code,
                     Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS
                     ne_length,
                     Round(SUM(CASE
                                 WHEN rj_construction_methodology NOT LIKE
                                      '%AERIAL%'
                                      AND rj_construction_methodology NOT LIKE
                                          '%CLAMP%'
                                       OR rj_construction_methodology IS NULL
                               THEN
                                 Nvl(calculated_length, 0)
                                 ELSE 0
                               END) / 1000, 4)                       AS
                     ug_length,
                     Round(SUM(CASE
                                 WHEN rj_construction_methodology LIKE
                                      '%AERIAL%'
                                       OR rj_construction_methodology LIKE
                                          '%CLAMP%'
                               THEN
                                 Nvl(calculated_length, 0)
                                 ELSE 0
                               END) / 1000, 4)                       AS
                     ar_length
              FROM   ne.mv_span@ne
              --  FROM APP_FTTX.span@sat
              WHERE  Trim(rj_span_id) = pspan_id
                     AND inventory_status_code = 'IPL'
                     AND NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9',
                             'i')
                     AND rj_maintenance_zone_code = pmaintzonecode
              GROUP  BY rj_span_id,
                        rj_maintenance_zone_code; 
                        
END;                        
ELSE

    
WITH    
    q1_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( SELECT   rj_span_id AS SPAN_ID,
                  rj_maintenance_zone_code AS maint_zone_code,
                  Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS NE_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology NOT LIKE '%AERIAL%'
                           AND      rj_construction_methodology NOT LIKE '%CLAMP%'
                           OR       rj_construction_methodology IS NULL THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS UG_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology LIKE '%AERIAL%'
                           OR       rj_construction_methodology LIKE '%CLAMP%' THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS AR_LENGTH
         FROM     ne.mv_span@ne
         WHERE    Trim(rj_span_id) = PSPAN_ID
         AND      inventory_status_code = 'IPL'
         AND      NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9', 'i')
         AND      rj_maintenance_zone_code = PMAINTZONECODE
         GROUP BY rj_span_id,
                  rj_maintenance_zone_code
        ), 
    q2_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( 
        SELECT span_id as SPAN_ID,
              maintenancezonecode       AS MAINT_ZONE_CODE,
              maint_zone_ne_span_length AS NE_LENGTH,
              fsa_ug                    AS UG_LENGTH,
              fsa_aerial                AS AR_LENGTH
       FROM   tbl_fiber_inv_jobs
       WHERE  span_id = PSPAN_ID
        )
SELECT     
            q1.SPAN_ID, q1.MAINT_ZONE_CODE, 
            q1.NE_LENGTH - Nvl(q2.NE_LENGTH, 0) as NE_LENGTH, 
            q1.UG_LENGTH - Nvl(q2.UG_LENGTH, 0) as UG_LENGTH,
            q1.AR_LENGTH - Nvl(q2.AR_LENGTH, 0) as AR_LENGTH
            
FROM        q1_data q1
LEFT JOIN   q2_data q2  ON(q2.SPAN_ID = q1.SPAN_ID)
ORDER BY    q1.SPAN_ID, q1.MAINT_ZONE_CODE;
                 
        
      END IF;
  END get_spaninfo_by_span_mz_new;

更新2:修改后的存储过程版本

PROCEDURE Get_spaninfo_by_span_mz_new 
(
    pspan_id       IN NVARCHAR2, 
    pmaintzonecode IN VARCHAR2, 
    pspantype      IN NVARCHAR2, 
    pspaninfodata  OUT SYS_REFCURSOR
)
  AS
  VAR_PARTIAL_QTY NUMBER; 
  
 BEGIN  
  VAR_PARTIAL_QTY :=0;
  
  
SELECT COUNT(JOB_ID) INTO  VAR_PARTIAL_QTY from tbl_fiber_inv_jobs 
        where span_id = PSPAN_ID
AND JOB_FLAG = 1;

WITH    
    q1_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( SELECT   rj_span_id AS SPAN_ID,
                  rj_maintenance_zone_code AS maint_zone_code,
                  Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS NE_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology NOT LIKE '%AERIAL%'
                           AND      rj_construction_methodology NOT LIKE '%CLAMP%'
                           OR       rj_construction_methodology IS NULL THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS UG_LENGTH,
                  Round(SUM(
                  CASE
                           WHEN rj_construction_methodology LIKE '%AERIAL%'
                           OR       rj_construction_methodology LIKE '%CLAMP%' THEN Nvl(calculated_length, 0)
                           ELSE 0
                  END) / 1000, 4) AS AR_LENGTH
         FROM     ne.mv_span@ne
         WHERE    Trim(rj_span_id) = PSPAN_ID
         AND      inventory_status_code = 'IPL'
         AND      NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9', 'i')
         AND      rj_maintenance_zone_code = PMAINTZONECODE
         GROUP BY rj_span_id,
                  rj_maintenance_zone_code
        ), 
    q2_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
        ( 
        SELECT span_id as SPAN_ID,
              maintenancezonecode       AS MAINT_ZONE_CODE,
              maint_zone_ne_span_length AS NE_LENGTH,
              fsa_ug                    AS UG_LENGTH,
              fsa_aerial                AS AR_LENGTH
       FROM   tbl_fiber_inv_jobs
       WHERE  span_id = PSPAN_ID
        );
        


              IF pspantype = 'INTERCITY' AND Length(pspan_id) = 21 
                 AND VAR_PARTIAL_QTY = 0
              THEN
        
BEGIN
            OPEN pspaninfodata FOR

            SELECT rj_span_id AS span_id, rj_maintenance_zone_code AS maint_zone_code,
                     Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS ne_length,
                     Round(SUM(CASE
                                 WHEN rj_construction_methodology NOT LIKE
                                      '%AERIAL%' AND rj_construction_methodology NOT LIKE
                                          '%CLAMP%' OR rj_construction_methodology IS NULL
                               THEN
                                 Nvl(calculated_length, 0) ELSE 0 END) / 1000, 4)  AS UG_LENGTH,
                     Round(SUM(CASE WHEN rj_construction_methodology LIKE '%AERIAL%'
                                       OR rj_construction_methodology LIKE '%CLAMP%'
                               THEN
                                 Nvl(calculated_length, 0) ELSE 0 END) / 1000, 4) AS AR_LENGTH
              FROM   ne.mv_span@ne
              WHERE  Trim(rj_span_id) = pspan_id
                     AND inventory_status_code = 'IPL'
                     AND NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9',
                             'i')
                     AND rj_maintenance_zone_code = pmaintzonecode
              GROUP  BY rj_span_id,
                        rj_maintenance_zone_code;
        END;    
        
ELSE        
     
     OPEN pspaninfodata FOR
     
     SELECT     
            q1_data.SPAN_ID, q1_data.MAINT_ZONE_CODE, 
            q1_data.NE_LENGTH - Nvl(q2_data.NE_LENGTH, 0) as NE_LENGTH, 
            q1_data.UG_LENGTH - Nvl(q2_data.UG_LENGTH, 0) as UG_LENGTH,
            q1_data.AR_LENGTH - Nvl(q2_data.AR_LENGTH, 0) as AR_LENGTH
            
FROM        q1_data q1
LEFT JOIN   q2_data q2  
ON(q2.SPAN_ID = q1.SPAN_ID)
ORDER BY    q1.SPAN_ID, q1.MAINT_ZONE_CODE;
     
END IF;            
 
END Get_spaninfo_by_span_mz_new; 

问题分析与解决

原始查询错误原因

原始查询中已给q1_data、q2_data分别取了别名q1、q2,但SELECT字段里却用原CTE名称q1_data、q2_data引用字段,不符合SQL语法,需改用别名访问:

SELECT     
    q1.SPAN_ID, q1.MAINT_ZONE_CODE, 
    q1.NE_LENGTH - Nvl(q2.NE_LENGTH, 0) as NE_LENGTH, 
    q1.UG_LENGTH - Nvl(q2.UG_LENGTH, 0) as UG_LENGTH,
    q1.AR_LENGTH - Nvl(q2.AR_LENGTH, 0) as AR_LENGTH
FROM        q1_data q1
LEFT JOIN   q2_data q2  ON(q2.SPAN_ID = q1.SPAN_ID)
ORDER BY    q1.SPAN_ID, q1.MAINT_ZONE_CODE;

更新2版本错误原因

更新2中将WITH子句单独放在IF语句外,这是错误的。PL/SQL中WITH子句属于SELECT语句的一部分,作用域仅限于紧跟的SELECT语句,无法单独定义后在后续语句中引用。

正确做法是将WITH子句放在ELSE分支的OPEN pspaninfodata FOR后,作为游标查询的一部分:

ELSE        
    OPEN pspaninfodata FOR
    WITH    
        q1_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
            ( SELECT   rj_span_id AS SPAN_ID,
                      rj_maintenance_zone_code AS maint_zone_code,
                      Round(SUM(Nvl(calculated_length, 0) / 1000), 4) AS NE_LENGTH,
                      Round(SUM(
                      CASE
                               WHEN rj_construction_methodology NOT LIKE '%AERIAL%'
                               AND      rj_construction_methodology NOT LIKE '%CLAMP%'
                               OR       rj_construction_methodology IS NULL THEN Nvl(calculated_length, 0)
                               ELSE 0
                      END) / 1000, 4) AS UG_LENGTH,
                      Round(SUM(
                      CASE
                               WHEN rj_construction_methodology LIKE '%AERIAL%'
                               OR       rj_construction_methodology LIKE '%CLAMP%' THEN Nvl(calculated_length, 0)
                               ELSE 0
                      END) / 1000, 4) AS AR_LENGTH
               FROM     ne.mv_span@ne
               WHERE    Trim(rj_span_id) = PSPAN_ID
               AND      inventory_status_code = 'IPL'
               AND      NOT Regexp_like (Nvl(rj_intracity_link_id, '-'), '_9', 'i')
               AND      rj_maintenance_zone_code = PMAINTZONECODE
               GROUP BY rj_span_id,
                        rj_maintenance_zone_code
            ), 
        q2_data (SPAN_ID, MAINT_ZONE_CODE, NE_LENGTH, UG_LENGTH, AR_LENGTH) AS
            ( 
            SELECT span_id as SPAN_ID,
                  maintenancezonecode       AS MAINT_ZONE_CODE,
                  maint_zone_ne_span_length AS NE_LENGTH,
                  fsa_ug                    AS UG_LENGTH,
                  fsa_aerial                AS AR_LENGTH
           FROM   tbl_fiber_inv_jobs
           WHERE  span_id = PSPAN_ID
            )
    SELECT     
        q1.SPAN_ID, q1.MAINT_ZONE_CODE, 
        q1.NE_LENGTH - Nvl(q2.NE_LENGTH, 0) as NE_LENGTH, 
        q1.UG_LENGTH - Nvl(q2.UG_LENGTH, 0) as UG_LENGTH,
        q1.AR_LENGTH - Nvl(q2.AR_LENGTH, 0) as AR_LENGTH
    FROM        q1_data q1
    LEFT JOIN   q2_data q2  ON(q2.SPAN_ID = q1.SPAN_ID)
    ORDER BY    q1.SPAN_ID, q1.MAINT_ZONE_CODE;
END IF;

以上修改可解决ORA-00904标识符无效错误,确保WITH子句在正确作用域内使用。


内容的提问来源于stack exchange,提问作者Nadeem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 04:36:00