【问题标题】:"local collection types not allowed" error in PL/SQL ORA-06550PL/SQL ORA-06550 中的“不允许本地集合类型”错误
【发布时间】:2012-01-17 12:45:18
【问题描述】:

我正在尝试从名为“sys.all_objects”的 oracle 表中获取查询 进入一个字符串变量,然后我可以将它作为输入提供给“dbms_obfuscation_toolkit.DESEncrypt”,之后加密的字符串将进入“utl_file”,这样我就可以将它写入一个txt文件。

这是问题,当我尝试使用此代码进行查询时;

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;

【问题讨论】:

    标签: sql oracle plsql ora-06550


    【解决方案1】:

    这只是对 A.B.Cade 的回答的澄清。光标与问题无关。

    根本原因

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

    is 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;
    /
    

    【讨论】:

      【解决方案2】:

      尝试使用游标和 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;
      

      没有检查代码

      【讨论】:

      • 你好 A.B.Cade,当我执行你的代码时,它给出了这个错误; ORA-22165:给定索引 [51] 必须在 [1] 到 [50] 的范围内 ORA-06512:在第 12 行,当我将“array(50)”更改为“array(100)”时,它显示给定索引[101] 必须在 [1] 到 [100] 的范围内仍在尝试解决此问题,但您有什么想法吗?
      • 然后尝试不同类型的集合,即 TYPE name_array 是 varchar2(100) 的表;
      • 确实有效,非常感谢。数组不工作的原因是,查询返回了 18000 个结果,数组太短了,我只尝试了 5000 个,没想到会有那么多回报。
      【解决方案3】:

      只需使用下面给定的块即可成功执行:

      DECLARE
      TYPE name_array is array(50) OF varchar2(100);
      var_input  name_array; 
      
      BEGIN
      SELECT owner Bulk Collect
        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;
      

      【讨论】:

        【解决方案4】:

        试试这个:

        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;
        

        或者这个:

        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;
        

        【讨论】:

        • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-16
        相关资源
        最近更新 更多