2017-07-25 78 views
0
CREATE TABLE T1 (EMP_NAME VARCHAR2 (40)); 

    INSERT INTO t1 
     VALUES ('Vinoth'); 

    COMMIT; 

    CREATE TABLE T2 (EMP_NAME VARCHAR2 (40)); 

    CREATE OR REPLACE PACKAGE TEST_PKG_V 
    AS 
     PROCEDURE P_MAIN (p_status OUT VARCHAR2); 

     TYPE T1_TYPE IS RECORD (EMP_NAME T1.EMP_NAME%TYPE); 

     TYPE T1_TBL IS TABLE OF T1_TYPE; 
    END TEST_PKG_V; 
    /

    CREATE OR REPLACE PACKAGE BODY TEST_PKG_V 
    AS 
     PROCEDURE P_MAIN (p_status OUT VARCHAR2) 
     IS 
      LV_T1_TBL T1_TBL := T1_TBL(); 

      CURSOR T1_CUR 
      IS 
      (SELECT EMP_NAME FROM t1); 

     BEGIN 
      OPEN T1_CUR; 

      LOOP 
      FETCH T1_CUR 
       BULK COLLECT INTO LV_T1_TBL 
       LIMIT 10000; 

      INSERT INTO t2 (EMP_NAME) 
       SELECT EMP_NAME FROM TABLE (LV_T1_TBL); 

      EXIT WHEN T1_CUR%NOTFOUND; 
      END LOOP; 

      COMMIT; 
     EXCEPTION 
      WHEN OTHERS 
      THEN 
      p_status := 'FAIL'; 
      RAISE; 
     END P_MAIN; 
    END TEST_PKG_V; 
/
DECLARE 
VAR VARCHAR2(4000); 
BEGIN 
TEST_PKG_V.P_MAIN(VAR); 
END; 

执行过程时抛出ORA-00902:无效的数据类型。 如果我注释掉过程中的insert语句,它运行得很好。这里有什么问题,并帮助我解决问题。Oracle:执行过程中抛出无效的数据类型错误ORA-00902:无效的数据类型

+1

用途:'FORALL INDX IN 1 .. LV_T1_TBL.COUNT LOOP INSERT INSERT INTO T2(EMP_NAME)VALUES(LV_T1_TBL(INDX)); END LOOP;'我插入你的插入语句。有关FORALL语句的更多信息,请参见[此处](http://www.oracle.com/technetwork/issue-archive/2012/12-sep/o52plsql-1709862.html)。 – krokodilko

回答

0

为了能够做到这一点,必须在包装之外创建类型。这是更正后的版本。缺点是,创建类型时,如果您更改表来更改列的类型,则可能会忘记修改类型。

CREATE TYPE T1_TYPE AS OBJECT (EMP_NAME VARCHAR2(40)); 
CREATE TYPE T1_TBL AS TABLE OF T1_TYPE; 

CREATE OR REPLACE PACKAGE TEST_PKG_V 
AS 
    PROCEDURE P_MAIN (p_status OUT VARCHAR2); 
END TEST_PKG_V; 
/

CREATE OR REPLACE PACKAGE BODY TEST_PKG_V 
AS 
    PROCEDURE P_MAIN (p_status OUT VARCHAR2) 
    IS 
     LV_T1_TBL T1_TBL; 

     CURSOR T1_CUR 
     IS 
     (SELECT T1_TYPE(EMP_NAME) EMP_NAME FROM t1); 

    BEGIN 
     OPEN T1_CUR; 

     LOOP 
     FETCH T1_CUR 
      BULK COLLECT INTO LV_T1_TBL 
      LIMIT 10000; 

     INSERT INTO t2 (EMP_NAME) 
      SELECT EMP_NAME FROM TABLE (LV_T1_TBL); 

     EXIT WHEN T1_CUR%NOTFOUND; 
     END LOOP; 

     COMMIT; 
    EXCEPTION 
     WHEN OTHERS 
     THEN 
     p_status := 'FAIL'; 
     RAISE; 
    END P_MAIN; 
END TEST_PKG_V; 
/

如果你希望你的类型是通用的,适应你的表,我想你会做这样的事情:

CREATE OR REPLACE PACKAGE TEST_PKG_V AS 

    TYPE T1_TYPE IS RECORD (EMP_NAME T1.EMP_NAME%TYPE); 
    TYPE T1_TBL IS TABLE OF T1_TYPE; 

    PROCEDURE P_MAIN (p_status OUT VARCHAR2); 
    FUNCTION GET_T1 RETURN T1_TBL PIPELINED; 

END TEST_PKG_V; 
/

CREATE OR REPLACE PACKAGE BODY TEST_PKG_V IS 

CURSOR T1_CUR IS (SELECT EMP_NAME FROM t1); 

FUNCTION GET_T1 RETURN T1_TBL PIPELINED IS 
    LV_T1_TBL T1_TBL; 
BEGIN 
    OPEN T1_CUR; 
    FETCH T1_CUR BULK COLLECT INTO LV_T1_TBL; 
    CLOSE T1_CUR; 
    FOR IDX IN 1..LV_T1_TBL.COUNT LOOP 
    PIPE ROW (LV_T1_TBL(IDX)); 
    END LOOP; 
END; 

PROCEDURE P_MAIN (p_status OUT VARCHAR2) IS 
BEGIN 
    INSERT INTO t2 (EMP_NAME) SELECT EMP_NAME FROM TABLE (GET_T1); 
    COMMIT; 
EXCEPTION 
    WHEN OTHERS THEN 
    p_status := 'FAIL'; 
    RAISE; 
END P_MAIN; 
END TEST_PKG_V; 
/

或者,您也可以通过迭代直接做光标:

CREATE OR REPLACE PACKAGE TEST_PKG_V AS 

    TYPE T1_TYPE IS RECORD (EMP_NAME T1.EMP_NAME%TYPE); 
    TYPE T1_TBL IS TABLE OF T1_TYPE; 
    PROCEDURE P_MAIN (p_status OUT VARCHAR2); 

END TEST_PKG_V; 
/

CREATE OR REPLACE PACKAGE BODY TEST_PKG_V IS 

PROCEDURE P_MAIN (p_status OUT VARCHAR2) IS 
    CURSOR T1_CUR IS (SELECT EMP_NAME FROM t1); 
BEGIN 
    FOR CURRENT_ROW IN T1_CUR LOOP 
    INSERT INTO t2 (EMP_NAME) VALUES (CURRENT_ROW.EMP_NAME); 
    END LOOP; 
    COMMIT; 
EXCEPTION 
    WHEN OTHERS THEN 
    p_status := 'FAIL'; 
    RAISE; 
END P_MAIN; 

END TEST_PKG_V; 
/
相关问题