2017-07-25 961 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; 
/
相關問題