Ошибка "локальные типы коллекций не допускаются" в PL/SQL ORA-06550

Я пытаюсь получить запрос из таблицы оракула с именем "sys.all_objects" в строковую переменную, поэтому я могу передать его "dbms_obfuscation_toolkit.DESEncrypt" в качестве входных данных, после чего зашифрованная строка перейдет в "utl_file", поэтому я можете записать его в текстовый файл.

Вот проблема, когда я пытаюсь сделать запрос с этим кодом;

DECLARE
TYPE name_array is array(50) OF varchar2(100);
var_input  name_array; 

BEGIN
SELECT owner
  INTO var_input
  FROM sys.all_objects;

  FOR i IN var_input.FIRST .. var_input.LAST
    LOOP
        dbms_output.put_line(var_input(i));
    END LOOP;
END;

и ошибка есть;

ORA-06550: line 7, column 12:
PLS-00642: local collection types not allowed in SQL statements

Любая идея о прохождении этой проблемы?

для тех, кто хочет увидеть полный код;

CREATE OR REPLACE DIRECTORY data AS 'd:\folder';
GRANT read, write ON DIRECTORY data TO PUBLIC;

DECLARE
var_input  varchar2(64) := 'Rndminpt';
var_key    varchar2(16) := 'Anahtar1'; 
var_enc    varchar2(1024);
var_dec    varchar2(1024);
var_file   utl_file.file_type;

BEGIN

-- (query part)

    dbms_obfuscation_toolkit.DESEncrypt(
        input_string     =>  var_input,
        key_string       =>  var_key,
        encrypted_string =>  var_enc);
    dbms_output.put_line('Encrypted...');

var_file := utl_file.fopen('DATA','textfile.txt','W');            
    utl_file.put_line(var_file,var_enc);
    utl_file.fclose(var_file);        
dbms_output.put_line('Writen in to text... ');      
END;

4 ответа

Решение

Попробуйте вместо этого использовать курсоры и BULK COLLECT: http://www.dba-oracle.com/t_oracle_bulk_collect.htm

должен выглядеть примерно так:

DECLARE
TYPE name_array is array(50) OF varchar2(100);
var_input  name_array; 


cursor c1 is
SELECT owner
  FROM sys.all_objects;

BEGIN
    open c1;
    fetch c1 bulk collect into var_input;
    close c1;

  FOR i IN var_input.FIRST .. var_input.LAST
    LOOP
        dbms_output.put_line(var_input(i));
    END LOOP;
END;

Не проверял код

Это просто разъяснение к ответу ABCade. Курсор не имеет ничего общего с проблемой.

Коренная причина

PLS-00642: local collection types not allowed in SQL statements

является sql into может использоваться только с переменной или записью PL/SQL, но не с коллекцией PL/SQL.

С коллекциями PL/SQL нужно использовать select bulk collect into вместо.

(Да - я согласен, что сообщение об ошибке может быть более информативным.)

Смотрите также:

Примеры

Следующий анонимный блок компилируется с PLS-00642, потому что select into нельзя использовать с коллекциями:

declare
  type dual_list_t is table of dual%rowtype;
  v_duals dual_list_t;
begin
  select *
    into v_duals
    from dual
  connect by level <= 2
  ;
end;
/

Следующий анонимный блок компилируется нормально:

declare
  type dual_list_t is table of dual%rowtype;
  v_duals dual_list_t;
begin
  select *
    bulk collect into v_duals
    from dual
  connect by level <= 2
  ;
end;
/

Просто используйте приведенный ниже блок для успешного выполнения:

ОБЪЯВЛЕНИЕ ТИПА name_array - это массив (50) OF varchar2(100); var_input name_array;

НАЧАТЬ ВЫБРАТЬ владельца Массовый сбор INTO var_inputFROM sys.all_objects;

FOR i IN var_input.FIRST .. var_input.LASTLOOPdbms_output.put_line(var_input(i)); КОНЕЦ ПЕТЛИ; КОНЕЦ;

          DECLARE 
    TYPE name_array IS ARRAY(50) OF VARCHAR2(100); 
    var_input name_array := name_array(); 
    idx NUMBER := 1; 
    BEGIN 
    var_input.extend; 
    SELECT owner INTO var_input (idx) FROM sys.all_objects WHERE object_id = 540;
    FOR i IN var_input.first..var_input.last LOOP
        dbms_output.put_line(var_input(i));
    END LOOP;
    END;
    
    .......................... or ...........................
    
    DECLARE
    TYPE name_array IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(50); 
    var_input name_array;
    BEGIN 
    FOR x IN 535..546 LOOP 
    SELECT owner INTO var_input (x) FROM sys.all_objects WHERE object_id = x;
    END LOOP;
    FOR i IN var_input.first..var_input.last LOOP
        dbms_output.put_line(var_input(i));
    END LOOP;
    END;
Другие вопросы по тегам