Тип пакета PL/SQL и тип схемы

Я пытаюсь сделать следующее:

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;

Но не компилируется:

Ошибка (16,14): PL/SQL: ORA-00902: неверный тип данных

Когда я определяю string_list_t вне пакета как

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

он компилируется и работает как положено. В чем здесь разница и как мне правильно это сделать с типом, определенным в пакете?


person vines    schedule 10.07.2011    source источник


Ответы (1)


Если вы собираетесь использовать оператор выбора SQL, который использует этот тип, то он должен быть типом SQL. Вы не можете вернуть тип PL/SQL в SQL.

Другой вариант, который может сработать, — создать цикл for и заполнить массив.

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; 
person Jeff Moore    schedule 10.07.2011
comment
Не могли бы вы рассказать немного о том, что такое тип SQL и что такое тип PL/SQL? - person vines; 11.07.2011
comment
@vines - под типом SQL он подразумевает тип, созданный на уровне схемы с помощью CREATE TYPE; под типом PL/SQL он подразумевает тип, объявленный внутри блока PL/SQL. Операторы SQL, даже находящиеся внутри блоков PL/SQL, не могут видеть объявления типа PL/SQL. - person Dave Costa; 11.07.2011
comment
@Jeff Джефф - возможно, вы могли бы сделать это с помощью BULK COLLECT INTO? - person Dave Costa; 11.07.2011
comment
@Джефф Мур, @Дэйв Коста: большое спасибо! bulk collect into самое главное, Джефф, пожалуйста, обнови ответ или Дейв — опубликуй свой, чтобы я мог отметить его как правильный :) - person vines; 11.07.2011
comment
Я обновил пример кода, чтобы показать пример массового сбора. - person Jeff Moore; 13.07.2011