Oracle:过程在执行期间抛出无效的数据类型错误ORA-00902:无效的数据类型

时间:2017-07-25 19:47:27

标签: oracle stored-procedures plsql bulkinsert

   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语句,它运行得很好。这有什么问题,帮助我解决问题。

1 个答案:

答案 0 :(得分: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;
/