如何调试下面PL/SQL块中invalid identifier的错误?

How to debug the error of invalid identifier in the following PL/SQL block?

对于以下 PLSQL 代码,我收到错误报告 - ORA-00904: "SRC"."PART_ID_CONSOLIDATED": 无效标识符 ORA-06512:在第 37 行,我尝试通过打印 I.item_no、I.PART_ID_CONSOLIDATED 的值来调试它,正确打印了值但仍然显示无效标识符,无法调试,请指导。

DECLARE
BEGIN
FOR T IN 
(
 SELECT * FROM TDTEMP.ITEM_MTRL_SPLIT_TMP
    where regexp_like(MATERIAL_NAME, '[[:digit:]],[[:digit:]] % +[[:alpha:]]*')
 ) 
 
  LOOP
   FOR I IN 
   
   (
   WITH parsed as(
    SELECT /*+ parallel(t,8) materialize */
    T.item_no,T.item_type,T.bu_code_sup,T.bu_type_sup,T.FROM_PACK_DATE,T.PART_ID,T.MATERIAL_NAME,T.PART_ID_CONSOLIDATED,T.reporting_name,
    regexp_substr(REGEXP_REPLACE(replace(replace(T.MATERIAL_NAME,'%  ','% '),', ',','), '(\d+),(\d+)', '.'),'[^,]+',1,ROWNUM) 
    AS split_value
      FROM dual
 CONNECT BY level <= regexp_count(REGEXP_REPLACE(replace(T.MATERIAL_NAME,'% /','%/'), '(\d+),(\d+)', '.'),'[^,]+')
)
,in_pairs as(
select /*+ parallel(k,8) materialize */
item_no,item_type,bu_code_sup,bu_type_sup,FROM_PACK_DATE,PART_ID,material_name,PART_ID_CONSOLIDATED,reporting_name
     ,regexp_substr(split_value, '[0-9]+[.]*[0-9]+') as percentage
      ,trim(substr(split_value, instr(split_value, '%') + 1)) as component
  from parsed k where split_value LIKE '%\%%' ESCAPE '\'
)
select /*+ parallel(it,8) */
distinct item_no,item_type,bu_code_sup,bu_type_sup,FROM_PACK_DATE,PART_ID,material_name,percentage,component,PART_ID_CONSOLIDATED,reporting_name
from in_pairs it 
)

 LOOP 
 
 
    merge into TDTEMP.ITEM_MTRL_SPLIT_TMP targ 
    using (
    SELECT I.item_no,I.item_type,I.bu_code_sup,I.bu_type_sup,I.FROM_PACK_DATE,I.PART_ID,I.material_name,I.percentage,I.component,I.PART_ID_CONSOLIDATED,
    I.reporting_name FROM DUAL
    )src
    on (         targ.item_no                   = src.item_no
              and  targ.item_type               = src.item_type
              and  targ.bu_code_sup             = src.bu_code_sup
              and  targ.bu_type_sup             = src.bu_type_sup
              and  targ.part_id                 = src.part_id
              and  targ.from_pack_date          = src.from_pack_date
              and  targ.component               = src.component
              and targ.percentage               = src.percentage
              and targ.material_name            = src.material_name
              and targ.PART_ID_CONSOLIDATED     = src.PART_ID_CONSOLIDATED
              )
     when not matched then
      insert (item_no   ,           
             item_type  ,       
             bu_code_sup,           
             bu_type_sup    ,       
             from_pack_date ,   
             part_id            ,   
             part_id_consolidated,
             material_name  ,   
             percentage ,       
             component  ,
             reporting_name,
             plastic, 
             ii_date    )
values( src.item_no ,       
        src.item_type   ,   
        src.bu_code_sup ,   
        src.bu_type_sup ,   
        src.from_pack_date, 
        src.part_id     ,   
        src.part_id_consolidated ,  
        src.material_name   ,   
        src.percentage  ,   
        src.component ,
        src.reporting_name,
        'N',
        sysdate 
        )
when  matched then
update set  targ.percentage                 =   src.percentage  ,
            targ.component                  =   src.component   ;
         
            
            END LOOP ;
            END LOOP ;
            
     END ;       

         
         

简短的回答是,因为您是从 dual 中选择的,它只有一个虚拟列,所以您需要为您在 using 子句中选择的所有值指定别名:

using (
  SELECT I.item_no AS item_no, I.item_type AS item_type, I.bu_code_sup AS bu_code_sup,
    I.bu_type_sup AS bu_type_sub, I.FROM_PACK_DATE AS from_pack_date,
    I.PART_ID AS part_id, I.material_name AS material_name, I.percentage AS percentage,
    I.component AS component, I.PART_ID_CONSOLIDATED AS part_id_consolidated,
    I.reporting_name AS reporting_name
  FROM DUAL
) src

db<>fiddle with a very simplified example. To some extent that also addresses the "how to debug" part of your question - break your failing block of code down into smaller and simpler parts to make it easier to see what's happening. And if you still can't work it out, you're much closer to a minimum reproducible example 你可以 post 没有那么多噪音让其他人涉水通过。

长答案是避免循环并进行一次合并,正如 MTO 在评论中所建议的那样。