集合类型作为游标参数

时间:2013-01-09 11:35:30

标签: sql oracle plsql cursor

我需要做一个接收列表作为参数的游标。我试过这个:

declare

type array_t is table of varchar(50); -- //also tried varray(10) instead of table

cursor c_cursor (p_list array_t) is
select 
    field_1
from 
    table_1
where 
    field_2 in p_list;

a_list array_t;

begin
    a_list := array_t('aaa',
        'bbb',
        'cccc',
        'ddd');

    for v_cursor in c_cursor(a_list) loop
        dbms_output.put_line(v_cursor.field_1);
    end loop;
end;

我收到以下错误

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

我已经阅读了有关使用CREATE OR REPLACE方法的内容,但在这种情况下我无法使用CREATE OR REPLACE(实际上数据库是只读的)。

有没有可能的解决方案?

3 个答案:

答案 0 :(得分:1)

您需要使用查询

分别创建type
CREATE OR REPLACE type array_t as table of varchar2(50);

请在此之后尝试。

答案 1 :(得分:0)

您需要SQL类型而不是pl / sql,然后使用table语法来使用它。

正如你所说,你无法创建一个,尝试在DBMS_OUTPUT上内置一个。

SQL> create table table_1(field_1 varchar2(20), field_2 varchar2(20));

Table created.

SQL> insert into table_1 values ('test', 'aaa');

1 row created.

SQL> insert into table_1 values ('test2', 'cccc');

1 row created.

SQL> insert into table_1 values ('test3', 'x');

1 row created.

SQL> commit;

Commit complete.

SQL> set serverout on
SQL> declare
  2  cursor c_cursor (p_list sys.DBMSOUTPUT_LINESARRAY) is
  3  select /*+ cardinality(p, 10) */
  4      field_1
  5  from
  6      table_1 t
  7      inner join table(p_list) p
  8              on t.field_2 = p.column_value;
  9
 10  a_list sys.DBMSOUTPUT_LINESARRAY;
 11
 12  begin
 13      a_list := sys.DBMSOUTPUT_LINESARRAY('aaa',
 14          'bbb',
 15          'cccc',
 16          'ddd');
 17
 18      for v_cursor in c_cursor(a_list) loop
 19          dbms_output.put_line(v_cursor.field_1);
 20      end loop;
 21  end;
 22  /
test
test2

/*+ cardinality(p, 10) */提示是告诉Oracle大概有多少行在数组中。放一个有代表性的数字,或者oracle会假设数组包含@ 8k行,这可能导致计划不佳。

答案 2 :(得分:0)

这可能会有所帮助 - Oracle PL / SQL:

DECLARE
  Type t_EmpNoArr IS VARRAY(20000) OF NUMBER(10) ;
  v_RetVal  t_EmpNoArr:= t_EmpNoArr();
  --
  FUNCTION retArray return t_EmpNoArr
  IS
    v_empnoArr t_EmpNoArr:= t_EmpNoArr();
  BEGIN
    FOR i IN ( SELECT empno FROM scott.emp )
    LOOP
      v_empnoArr.extend() ;
      v_empnoArr(v_empnoArr.count):= i.empno ;
    END LOOP;
  --
    FOR j IN 1..v_empnoArr.COUNT() LOOP
       DBMS_OUTPUT.PUT_LINE(v_empnoArr(j));
    END LOOP;
  --
  RETURN v_empnoArr;
 END retArray;
 --
 BEGIN
   v_RetVal:= retArray();
 END;
 /