1

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

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(实际上数据库是只读的)。

有没有可能的解决方案?

4

3 回答 3

2

您需要一种 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 行,这可能会导致计划不佳。

于 2013-01-09T11:53:21.697 回答
1

您需要type使用查询单独创建

CREATE OR REPLACE type array_t as table of varchar2(50);

请在那之后尝试。

于 2013-01-09T11:40:57.130 回答
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;
 /
于 2013-01-09T15:10:40.220 回答