我正在尝试创建一个将数据从一个表填充到另一个表的过程。如果存在列组合,则更新目标表中的两列。如果列的组合不存在,则在目标表中创建或覆盖记录。
有人/任何人可以帮我解决上述错误吗?我会感激你的。
这是程序。
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;
答案 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);
......应该做同样的事情;如果你愿意的话,你仍然可以把它放在一个程序里面。在程序中提交通常不被认为是个好主意,但你可能有合理的理由这样做。