0

私の手順

CREATE OR REPLACE PROCEDURE my_procedure(res OUT SYS_REFCURSOR , p_LstKH CLOB)
AS
CURSOR c_dsKH
  IS
    SELECT TO_NUMBER(REGEXP_SUBSTR(p_LstKH,'[^,]+', 1, level)) value FROM dual
    CONNECT BY REGEXP_SUBSTR(p_LstKH, '[^,]+', 1, level) IS NOT NULL;
BEGIN
...
END;

長い文字列 p_LstKH を分割して、CURSOR c_dsKH に入れたいと思います。例: p_LstKH = '1,2,....,10000'

c_dsKH.value
1
2
...
10000

しかし、その手順を実行すると、「操作で接続するためのメモリが不足しています」というエラーが表示されます。パラメータ p_LstKH CLOB を p_LstKH VARCHAR2 に置き換えようとすると、他のエラー「ORA-06502: PL/SQL: 数値または値エラー: 文字列バッファが小さすぎます」が発生します。

私は今どうすればいい ?簡単に言えば、長い文字列を分割したいと思います。皆さんありがとう !

4

2 に答える 2

2

コンマに基づいて独自の分割を行い、パイプライン化された関数を使用して値を返すことができます。

create or replace function split_clob(p_lstkh clob)
return sys.odcivarchar2list pipelined
as
  start_pos pls_integer := 0;
  end_pos pls_integer := 0;
  clob_length pls_integer;
  str varchar2(4000);
begin
  clob_length := dbms_lob.getlength(p_lstkh);
  while end_pos <= clob_length loop
    start_pos := end_pos + 1;
    end_pos := dbms_lob.instr(p_lstkh, ',', start_pos, 1);
    if end_pos <= 0 then
      end_pos := clob_length + 1;
    end if;
    str := dbms_lob.substr(p_lstkh, end_pos - start_pos, start_pos);
    pipe row (str);
  end loop;
end;
/

次に、それをテーブルとして扱うことができます。

select * from table(split_clob('X,Y,Z'));

COLUMN_VALUE
------------
X            
Y            
Z            

それでも参照カーソルとして使用したい場合は、プロシージャで connect-by の代わりにその選択をカーソルに使用できます。

32k を超える実際の (作成された) clob で動作することを示すデモとして:

declare
  clob_val clob := 'A,B,C,D,E,F,G,H,I';
begin
  for i in 1..2000 loop
    dbms_lob.append(clob_val, ',A,B,C,D,E,F,G,H,I');
  end loop;
  dbms_output.put_line('Clob size: ' || dbms_lob.getlength(clob_val));
  for r in (select * from table(split_clob(clob_val)) where rownum < 6) loop
    dbms_output.put_line(r.column_value);
  end loop;
end;
/

anonymous block completed
Clob size: 36017
A
B
C
D
E
于 2014-03-05T12:36:02.703 に答える