0

関数内でカーソルを返す必要があります。

CREATE OR REPLACE FUNCTION test_cursor (
   bigstring   IN   VARCHAR2
)
   RETURN cursor

IS
  row_test table_colors := table_colors(bigstring);
  c1 CURSOR;
BEGIN
   OPEN c1 FOR
      select * from cars where color IN (select column_value
                                    from table(row_test));

   RETURN c1;

END test_cursor;

table_colorsは:

create or replace type table_colors as table of varchar2(20);

しかし、テストすると、同じように渡すblue, red, pink, whiteか、'blue', 'red', 'pink', 'white'常に同じエラーがスローされます

ORA-06502: PL/SQL; numeric or value error: character string buffer too small

この行でrow table_colors := table_colors(bigstring);

ここで何が間違っていますか?

4

2 に答える 2

1

問題は、bigstring値のリストではなく、単一のスカラー値にコンマと単一引用符が含まれている可能性があることです。データ要素を抽出するには、文字列を解析する必要があります。内部の個々の要素のそれぞれがbigstringたまたま有効な Oracle 識別子である場合は、組み込みdbms_utility.comma_to_table関数を使用できます。しかし、それが私のシステムであれば、独自の構文解析機能の方が快適に感じるでしょう。bigstringこれが単なるコンマ区切りのリストであると仮定すると、Tom Kyte のstr2tbl 関数のバージョンを使用します。

create or replace function str2tbl( p_str in varchar2 ) 
  return table_colors
as
  l_str   long default p_str || ',';
  l_n        number;
  l_data    table_colors := table_colors();
begin
  loop
    l_n := instr( l_str, ',' );
    exit when (nvl(l_n,0) = 0);
    l_data.extend;
    l_data( l_data.count ) := ltrim(rtrim(substr(l_str,1,l_n-1)));
    l_str := substr( l_str, l_n+1 );
  end loop;
  return l_data;
end;

str2tblこれで、単一の SQL ステートメントでも正規表現を使用して現実的に実装できるようになりました。それはもう少し効率的かもしれません。ただし、文字列の解析はパフォーマンスの問題のリストのかなり下にあると予想されるため、機能する可能性のある最も単純なものに固執する傾向があります。

あなたの手順はその後になります

CREATE OR REPLACE FUNCTION test_cursor (
   bigstring   IN   VARCHAR2
)
   RETURN sys_refcursor
IS
  row_test table_colors := str2tbl(bigstring);
  c1 sys_refcursor;
BEGIN
   OPEN c1 FOR
      select * from cars where color IN (select column_value
                                           from table(row_test));

   RETURN c1;

END test_cursor;
于 2016-03-08T19:52:10.683 に答える
0

の定義を示してくださいtable_colors。はtable_colors(bigstring)への割り当てと互換性のない値を返しているようtable_colorsです。

適切な方法として、重要な値の初期化はbegin ... end、定義セクションではなく の内部で行う必要があります。これにより、エラーが外側にカスケードするのではなく、関数またはプロシージャ内でエラーをトラップできます。たとえば、次の代わりに:

IS
  row_test table_colors := table_colors(bigstring);
 c1 CURSOR;
BEGIN ...

使用する必要があります

IS
  row_test table_colors;
  c1 CURSOR;
BEGIN
  row_test := row_test;
  ...
于 2016-03-08T20:24:58.023 に答える