用pl\sql逐行读取clob

ily*_*tmn 2 oracle plsql plsqldeveloper

在我的项目中,我使用oracle作为主数据库,我遇到了解析clob的问题.所以假设我们有一个有价值的clob

   aaaaaa
   cccccc
   bbbbbb
Run Code Online (Sandbox Code Playgroud)

它存储在表格测试中......

我需要写plsql程序来获取这个clob并拆分它以便我将有三个项目的数组[aaaaaa,cccccccc,bbbbbbb].

有没有可能的解决方案?

Pie*_*ois 15

这是一段有用的代码.为了提高性能,我建议您使用显式游标而不是隐式游标(FOR i IN(select ...)).

首先是创建测试用例的脚本.

create table test (c clob);

insert into test (c) values (
'azertyuiop
qsdfghjklm
wxcvbn
');
Run Code Online (Sandbox Code Playgroud)

然后这里是逐行读取Clob的脚本:

/* Formatted on 28/08/2012 14:16:52 (QP5 v5.115.810.9015) */
declare
    nStartIndex number := 1;
    nEndIndex number := 1;
    nLineIndex number := 0;
    vLine varchar2(2000);

    cursor c_clob is
    select c from test;

    c clob;
    -------------------------------
    procedure printout
       (p_clob in out nocopy clob) is
      offset number := 1;
      amount number := 32767;
      len    number := dbms_lob.getlength(p_clob);
      lc_buffer varchar2(32767);
      i pls_integer := 1;
    begin
      if ( dbms_lob.isopen(p_clob) != 1 ) then
        dbms_lob.open(p_clob, 0);
      end if;
      amount := instr(p_clob, chr(10), offset);
      while ( offset < len )
      loop
        dbms_lob.read(p_clob, amount, offset, lc_buffer);
        dbms_output.put_line('Line #'||i||':'||lc_buffer);
       offset := offset + amount;
       i := i + 1;
      end loop; 
          if ( dbms_lob.isopen(p_clob) = 1 ) then
        dbms_lob.close(p_clob);
      end if; 
    exception
      when others then
         dbms_output.put_line('Error : '||sqlerrm);
    end printout;
    ---------------------------
begin
    dbms_output.put_line('-----------');
    open c_clob;
    loop
       fetch c_clob into c;
       exit when c_clob%notfound;
       printout(c);
    end loop;
    close c_clob;
end;
Run Code Online (Sandbox Code Playgroud)

'amount'变量用于检测行尾位置.Carfull,在某些情况下,行尾是CHR(10)|| CHR(13)(CR + LF),在其他一些情况下它只是CHR(10).


小智 6

虽然SQL regexp/connect by level方法可能是最优雅的,但在性能上却相当糟糕(对于我在11.2.0.3.0上的测试用例).这样一个简单的解析要快得多.

procedure parse_clob(p_clob in clob) is
l_offset pls_integer:=1;
l_line varchar2(32767);
l_total_length pls_integer:=length(p_clob);
l_line_length pls_integer;
begin
  while l_offset<=l_total_length loop
    l_line_length:=instr(p_clob,chr(10),l_offset)-l_offset;
    if l_line_length<0 then
      l_line_length:=l_total_length+1-l_offset;
    end if;
    l_line:=substr(p_clob,l_offset,l_line_length);
    dbms_output.put_line(l_line); --do line processing
    l_offset:=l_offset+l_line_length+1;
  end loop;
end parse_clob;
Run Code Online (Sandbox Code Playgroud)