Oracle过程错误PLS-00330,ORA-00904 ::无效标识符和错误(37,24):PLS-00382

时间:2016-07-29 14:35:04

标签: database cursor oracle-sqldeveloper procedure

我正在尝试创建一个将数据从一个表填充到另一个表的过程。如果存在列组合,则更新目标表中的两列。如果列的组合不存在,则在目标表中创建或覆盖记录。

有人/任何人可以帮我解决上述错误吗?我会感激你的。

这是程序。

create or replace PROCEDURE           "PRO_1_Table_2_another" AS

CURSOR C1_CUR IS
SELECT    D.D1
          ,SUBSTR(SISR.S1,1,4)
          ,SISR.S2
          ,SISR.S3
          ,SISR.S4
          ,SISR.S5
          ,SISR.S6
          ,SISR.S7
          ,SISR.S8
          ,SISR.S9
    FROM  something_in_system_record SISR
         ,Dump D
    WHERE SUBSTR(SISR.A1,1,4)=D.D1;

    TYPE C1_TA is table of C1_CUR%ROWTYPE;
    V_C1 C1_TA;

  BEGIN


   FOR i in C1_CUR LOOP

   V_C1 := C1_TA; --Error(26,12): PLS-00330: invalid use of type name or subtype name
          MERGE INTO In_something TGT
          USING
          (SELECT V_C1(i).A1 AS  A1,
                  V_C1(i).A2 AS  A2,
                  V_C1(i).A3 AS  A3,
                  V_C1(i).A4 AS  A4,
                  V_C1(i).A5 AS  A5,
                  V_C1(i).A6 AS  A6,
                  V_C1(i).A7 AS  A7,
                  V_C1(i).A8 AS  A8,
                  V_C1(i).A9 AS  A9 --Error(37,19): PL/SQL: ORA-00904: :invalid identifier &&& Error(37,24): PLS-00382: expression is of wrong type
          FROM DUAL) SRC
          ON     (SRC.A1 = TGT.A1
              AND SRC.A2 = TGT.A2
              AND SRC.A3 = TGT.A3
              AND SRC.A4 = TGT.A4
              AND SRC.A5 = TGT.A5
              AND SRC.A6 = TGT.A6
              AND SRC.A7 = TGT.A7
          )
          WHEN MATCHED THEN
            UPDATE SET TGT.A8 = SRC.A8,
                       TGT.A9 = SRC.A9
          WHEN NOT MATCHED THEN
          INSERT (TGT.A1
               ,TGT.A2
               ,TGT.A3
               ,TGT.A4
               ,TGT.A5
               ,TGT.A6
               ,TGT.A7
               ,TGT.A8
               ,TGT.A9)   
          VALUES 
              (SRC.S1
              ,SRC.S2
              ,SRC.S3
              ,SRC.S4
              ,SRC.S5
              ,SRC.S6
              ,SRC.S7
              ,SRC.S8
              ,SRC.S9);          
     END LOOP;
   COMMIT;
   EXCEPTION 
  WHEN OTHERS THEN 
  DBMS_OUTPUT.PUT_LINE(SQLCODE||' - '||SQLERRM);
END PRO_1_Table_2_another;

2 个答案:

答案 0 :(得分:0)

当您错过拼写列名称时,会出现ORA-00904: : invalid identifier

就像你有一个包含以下列的表Employee

|ID|Name|Address|

你写了一个像这样的DML语句,

select * from Employee where Adress like '%abcpqr%'

然后它将抛出此异常。 ORA-00904: : invalid identifier

希望它会有所帮助。

答案 1 :(得分:0)

您的C1_TA类型是一个集合,所以

V_C1 := C1_TA;

应该是:

V_C1 := C1_TA();

......但你不需要它;你正在混合不同的游标类型。您似乎已经编写了部分内容,就像批量收集到表类型中一样,然后使用i作为索引;但这里i是一种记录类型。你根本不需要你的表类型,或者它的变量实例。

您还没有为SUBSTR(SISR.S1,1,4)添加列别名,因此稍后提及S1并非有效;并且您在几个地方混淆了A1 / S1名称,这可能是通过手动更改真实列的名称来隐藏它们(这很好,但是一直这样做。)

因此纠正你所得到的所有内容:

create or replace PROCEDURE           "PRO_1_Table_2_another" AS

CURSOR C1_CUR IS
SELECT    D.D1
          ,SUBSTR(SISR.S1,1,4) AS S1
          ,SISR.S2
          ,SISR.S3
          ,SISR.S4
          ,SISR.S5
          ,SISR.S6
          ,SISR.S7
          ,SISR.S8
          ,SISR.S9
    FROM  something_in_system_record SISR
         ,Dump D
    WHERE SUBSTR(SISR.S1,1,4)=D.D1;

  BEGIN

   FOR i in C1_CUR LOOP

          MERGE INTO In_something TGT
          USING
          (SELECT i.S1 AS  A1,
                  i.S2 AS  A2,
                  i.S3 AS  A3,
                  i.S4 AS  A4,
                  i.S5 AS  A5,
                  i.S6 AS  A6,
                  i.S7 AS  A7,
                  i.S8 AS  A8,
                  i.S9 AS  A9
          FROM DUAL) SRC
          ON     (SRC.A1 = TGT.A1
              AND SRC.A2 = TGT.A2
              AND SRC.A3 = TGT.A3
              AND SRC.A4 = TGT.A4
              AND SRC.A5 = TGT.A5
              AND SRC.A6 = TGT.A6
              AND SRC.A7 = TGT.A7
          )
          WHEN MATCHED THEN
            UPDATE SET TGT.A8 = SRC.A8,
                       TGT.A9 = SRC.A9
          WHEN NOT MATCHED THEN
          INSERT (TGT.A1
               ,TGT.A2
               ,TGT.A3
               ,TGT.A4
               ,TGT.A5
               ,TGT.A6
               ,TGT.A7
               ,TGT.A8
               ,TGT.A9)   
          VALUES 
              (SRC.A1
              ,SRC.A2
              ,SRC.A3
              ,SRC.A4
              ,SRC.A5
              ,SRC.A6
              ,SRC.A7
              ,SRC.A8
              ,SRC.A9);          
     END LOOP;
   COMMIT;
   EXCEPTION 
  WHEN OTHERS THEN 
  DBMS_OUTPUT.PUT_LINE(SQLCODE||' - '||SQLERRM);
END "PRO_1_Table_2_another";
/

...但是您在光标中找到的每一行都进行了单独的合并,但这并不合理。你可以这样做:

MERGE INTO In_something TGT
USING (
    SELECT D.D1
          ,SUBSTR(SISR.S1,1,4) AS S1
          ,SISR.S2
          ,SISR.S3
          ,SISR.S4
          ,SISR.S5
          ,SISR.S6
          ,SISR.S7
          ,SISR.S8
          ,SISR.S9
    FROM  something_in_system_record SISR
    JOIN  Dump D
    ON    SUBSTR(SISR.S1,1,4)=D.D1
    ) SRC
ON  (
        SRC.S1 = TGT.A1
    AND SRC.S2 = TGT.A2
    AND SRC.S3 = TGT.A3
    AND SRC.S4 = TGT.A4
    AND SRC.S5 = TGT.A5
    AND SRC.S6 = TGT.A6
    AND SRC.S7 = TGT.A7
)
WHEN MATCHED THEN
  UPDATE SET TGT.A8 = SRC.S8,
             TGT.A9 = SRC.S9
WHEN NOT MATCHED THEN
INSERT (TGT.A1
     ,TGT.A2
     ,TGT.A3
     ,TGT.A4
     ,TGT.A5
     ,TGT.A6
     ,TGT.A7
     ,TGT.A8
     ,TGT.A9)   
VALUES 
    (SRC.S1
    ,SRC.S2
    ,SRC.S3
    ,SRC.S4
    ,SRC.S5
    ,SRC.S6
    ,SRC.S7
    ,SRC.S8
    ,SRC.S9);

......应该做同样的事情;如果你愿意的话,你仍然可以把它放在一个程序里面。在程序中提交通常不被认为是个好主意,但你可能有合理的理由这样做。