【问题标题】:Table function with bulk collection throws invalid datatype具有批量收集的表函数抛出无效的数据类型
【发布时间】:2013-06-10 21:26:16
【问题描述】:

我正在编写一个函数,我想用表函数包装它,这样我就可以与选择查询一起使用。

这是我的类型声明和我的函数的一些行

CREATE OR REPLACE PACKAGE TYPES 
    AS 
        TYPE CURSORTYPE IS REF CURSOR; 

        TYPE vbugsrec
          IS
             RECORD (
                bug_id     bugs.bug_id%TYPE,
                facility   bugs.facility%TYPE
             );

          TYPE vbugstable
          IS
             TABLE OF vbugsrec
                INDEX BY BINARY_INTEGER;

    END;


      /
    CREATE OR REPLACE PACKAGE BODY CustomQueries
    AS
       FUNCTION pendverifylist (myldapid   IN userpass.ldapalias%TYPE,
                                maxrows    IN PLS_INTEGER:= CustomQueries.maxrecords)
          RETURN types.vbugstable
       IS
          datarows    types.vbugstable; 
          var_useralias userpass.ldapalias%TYPE
                := UPPER (pendverifylist.myldapid) ;

        CURSOR pendverify_cur (
             cursor_var_alias         IN            userpass.ldapalias%TYPE,
             cursor_var_mybugstatus   IN            bugs.bug_status%TYPE,
             cursor_var_wild          IN            qa_list.component%TYPE
          )
          IS
             SELECT   buglist.bug_id, buglist.facility
               FROM   bugs buglist,
                      (SELECT   qa.product, qa.component
                         FROM   qa_list qa, userpass UP
                        WHERE   qa.qa_id = UP.userid
                                AND UP.ldapalias = cursor_var_alias) plist
              WHERE       buglist.bug_status = cursor_var_mybugstatus
                      AND buglist.smr_state IN (SELECT   fs.finalstate
                                                  FROM   finalstates fs)
                      AND buglist.facility = plist.product
                      AND (buglist.product LIKE plist.component
                           OR plist.component = cursor_var_wild);

       BEGIN

          OPEN pendverifylist.pendverify_cur (cursor_var_alias         => pendverifylist.var_useralias,
                                              cursor_var_mybugstatus   => CustomQueries.default_bugstatus,
                                              cursor_var_wild          => CustomQueries.wildcard);

          FETCH pendverifylist.pendverify_cur
             BULK COLLECT INTO   pendverifylist.datarows
             LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
                          CustomQueries.MAXRECORDS);

          CLOSE pendverifylist.pendverify_cur;

          RETURN pendverifylist.datarows;

       END pendverifylist;

    END CustomQueries;
    /

当我想使用下面的 TABLE 函数时,我得到 error.ORA-00902: invalid datatype

SELECT * FROM TABLE(CUSTOMQUERIES.PENDVERIFYLIST ( 'product', 50 ));

谁能帮助我在这里做错了什么?

提前致谢

【问题讨论】:

  • 您的类型需要在架构级别声明,而不是在您的包中,以便能够在 SQL 查询中使用它们。
  • 好吧对不起各位,我把整个事情都照原样发布了。
  • @AlexPoole 请立即检查问题。类型在模式级别声明
  • @Jeevan,您的类型仍未在模式级别声明,而是在包中。它们应该是数据库对象。应该看起来像这样:create or replace type vbugsrec as object (bug_id ...)

标签: oracle


【解决方案1】:

您正在尝试在纯 SQL 中使用包级类型,这是不允许的。包中声明的类型在 PL/SQL 外部(甚至在 PL/SQL 内的普通 SQL 语句中)不可见或无效。你正在做的事情的精简版:

create or replace package types as
    type my_rec_type is record (dummy dual.dummy%type);
    type my_table_type is table of my_rec_type index by binary_integer;
end types;
/

create or replace package p42 as
    function get_table return types.my_table_type;
end p42;
/

create or replace package body p42 as
    function get_table return types.my_table_type is
        my_table types.my_table_type;
    begin
        select * bulk collect into my_table from dual;
        return my_table;
    end get_table;
end p42;
/

select * from table(p42.get_table);

SQL Error: ORA-00902: invalid datatype

即使在包中,如果您有一个尝试使用表函数的过程,它也会出错。如果你添加了:

    procedure test_proc is
    begin
        for r in (select * from table(get_table)) loop
            null;
        end loop;
    end test_proc;

...包体编译将失败并显示ORA-22905: cannot access rows from a non-nested table item

您需要在架构级别声明类型,而不是在包中,因此使用 SQL create type command

create type my_obj_type is object (dummy varchar2(1));
/

create type my_table_type is table of my_obj_type;
/

create or replace package p42 as
    function get_table return my_table_type;
end p42;
/

create or replace package body p42 as
    function get_table return my_table_type is
        my_table my_table_type;
    begin
        select my_obj_type(dummy) bulk collect into my_table from dual;
        return my_table;
    end get_table;
end p42;
/

select * from table(p42.get_table);

DUMMY
-----
X

【讨论】:

    【解决方案2】:

    实际上,模式级别不需要有类型。您需要做的就是将函数定义为 PIPELINED。

    -- DEFINITION IN PCKG HEADER
    create or replace PACKAGE "AAA" IS
    
      TYPE t_record IS RECORD (
       aaa VARCHAR(20 CHAR),
       bbb VARCHAR(50 CHAR),
       ccc VARCHAR(10 CHAR)
      );
    
      TYPE t_collection is table of t_record;
    
      FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED;
    
    END AAA;
    
    -- PCKG BODY
    create or replace PACKAGE BODY AAA AS
    
    FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED AS 
        CURSOR k1 is SELECT aaa,bbb,ccc FROM table;
    BEGIN
      FOR rec IN k1
      LOOP
         pipe row( (rec) );
      END LOOP;    
    END get_records
    END AAA;
    
    -- CALLING FUNCTION OUTSIDE OF PCKG
    select * from TABLE(AAA.get_records(par1, par2));
    

    【讨论】:

      【解决方案3】:

      感谢亚历克斯·普尔。这就是我最终的结果

      CREATE OR REPLACE TYPE vbugsrec
            IS
               OBJECT (
                  bug_id     NUMBER(9),
                  facility   VARCHAR2(256)
               );
      
      CREATE OR REPLACE TYPE vbugstable
            IS
               TABLE OF vbugsrec;
      /
      CREATE OR REPLACE PACKAGE BODY CustomQueries
      AS
         FUNCTION pendverifylist (myldapid   IN userpass.ldapalias%TYPE,
                                  maxrows    IN PLS_INTEGER:= CustomQueries.maxrecords)
            RETURN vbugstable
         IS
            datarows    vbugstable := vbugstable(); 
      
            var_useralias userpass.ldapalias%TYPE:= UPPER (pendverifylist.myldapid) ;
      
            TYPE temp_rec IS RECORD (
                                bug_id     bugs.bug_id%TYPE,
                                facility   bugs.facility%TYPE
                             );
      
            TYPE temp_records
            IS
               TABLE OF temp_rec
                  INDEX BY BINARY_INTEGER;
      
            temporary_records   temp_records;
      
          CURSOR pendverify_cur (
               cursor_var_alias         IN            userpass.ldapalias%TYPE,
               cursor_var_mybugstatus   IN            bugs.bug_status%TYPE,
               cursor_var_wild          IN            qa_list.component%TYPE
            )
            IS
               SELECT   buglist.bug_id, buglist.facility
                 FROM   bugs buglist,
                        (SELECT   qa.product, qa.component
                           FROM   qa_list qa, userpass UP
                          WHERE   qa.qa_id = UP.userid
                                  AND UP.ldapalias = cursor_var_alias) plist
                WHERE       buglist.bug_status = cursor_var_mybugstatus
                        AND buglist.smr_state IN (SELECT   fs.finalstate
                                                    FROM   finalstates fs)
                        AND buglist.facility = plist.product
                        AND (buglist.product LIKE plist.component
                             OR plist.component = cursor_var_wild);
      
         BEGIN
      
            OPEN pendverifylist.pendverify_cur (cursor_var_alias         => pendverifylist.var_useralias,
                                                cursor_var_mybugstatus   => CustomQueries.default_bugstatus,
                                                cursor_var_wild          => CustomQueries.wildcard);
      
            FETCH pendverifylist.pendverify_cur
               BULK COLLECT INTO   temporary_records
               LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
                            CustomQueries.MAXRECORDS);
      
            CLOSE pendverifylist.pendverify_cur;
      
            IF temporary_records.COUNT <> 0
            THEN
                FOR rec_idx IN temporary_records.FIRST .. temporary_records.LAST
                LOOP
                   datarows.EXTEND;
                   datarows (datarows.LAST) :=
                      vbugsrec (temporary_records (rec_idx).bug_id,
                                      temporary_records (rec_idx).facility);
                END LOOP;
            END IF;
      
            RETURN pendverifylist.datarows;
      
         END pendverifylist;
      
      END CustomQueries;
      /
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-25
        • 2018-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多