Search code examples
oracle-databaseplsqlpackageplsqldevelopernested-table

PL/SQL package type vs schema type


What I'm trying to do is the following:

create or replace
package MyPackage
as
    type string_list_t is table of varchar2(32767);

    function GetPrimaryKeys    ( p_table_name varchar2, p_owner varchar2 )
        return string_list_t;
end MyPackage;
/

create or replace
package body MyPackage as

function GetPrimaryKeys ( p_table_name varchar2, p_owner varchar2 )
return string_list_t
is
    pk_descr string_list_t;
begin
    select cast( multiset (
        select cols.column_name
          from all_constraints cons, all_cons_columns cols
          where cols.table_name = p_table_name
          and cons.constraint_type = 'P'
          and cons.constraint_name = cols.constraint_name
          and cols.owner = p_owner
          and cons.owner = p_owner
    ) as string_list_t) into pk_descr from dual; -- error refers to string_list_t

     return pk_descr;
end;

end MyPackage;

But it doesn't compile:

Error(16,14): PL/SQL: ORA-00902: invalid datatype

When I define string_list_t outside of the package as

create or replace
type string_list_t is table of varchar2(32767);

it compiles and works as expected. What makes the difference here and how do I do it correctly with the type defined in package?


Solution

  • If you are going to use a SQL select statement that uses the type, then it must be a SQL type. You cannot return a PL/SQL type to SQL.

    Another option that might work is to create a for loop and populate the array.

    CREATE OR REPLACE PACKAGE BODY MyPackage as
    
      function GetPrimaryKeys ( p_table_name varchar2, p_owner varchar2 ) return string_list_t
      is
        pk_descr string_list_t;
        --iCounter  number:=1;
      begin
    
        /*------------------------------
         -       new version                 
         ------------------------------*/
        SELECT cols.column_name
          BULK COLLECT INTO pk_descr
        FROM   all_constraints cons, 
               all_cons_columns cols
        WHERE  cols.table_name = p_table_name
          AND  cons.constraint_type = 'P'
          AND  cons.constraint_name = cols.constraint_name
          AND  cols.owner = p_owner
          AND  cons.owner = p_owner;
    
        /* old version */
        FOR rec in (select cols.column_name
                    from   all_constraints cons, 
                           all_cons_columns cols
                    where  cols.table_name = p_table_name
                      and  cons.constraint_type = 'P'
                      and cons.constraint_name = cols.constraint_name
                      and cols.owner = p_owner
                      and cons.owner = p_owner) 
        LOOP
    
          pk_descr(iCounter):= rec.column_name;
          iCounter:= iCounter+1;
        END LOOP;
    
    
        RETURN pk_descr;
     END;
    
    END MyPackage;