需要使用PLSQL将CLOB文件数据写入ORACLE表

时间:2015-03-05 09:16:02

标签: sql database plsql oracle11g

我在clob字段中有平面文件,平面文件的结构如下所示。和平面文件包含数百万条记录。

col1,col2,col3,col4,col5,col6
A,B,C,,F,D
1,A,2,B,B,C

我不能使用的传统方式

从excel中的clob中获取数据,并使用sql-loader将数据加载到表中。

2 - 目前我可以使用以下代码打印clob文件。

OPEN c_clob;
LOOP
FETCH c_clob INTO c;
EXIT
WHEN c_clob%notfound;
printout(c);

但上面代码中的问题是如果我将此变量用于insert语句,那么由于CLOB到VAR插入它会产生错误。

INSERT INTO Table1 VALUES(c);
commit;

ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 848239, maximum: 4000)

是否还有其他选项可用于处理来自clob字段的大型平面文件并转储到表中。

目前我正在使用以下代码

declare nStartIndex number := 1; nEndIndex number := 1; nLineIndex number := 0; vLine varchar2(2000); cursor c_clob is select char_data from clob_table where seq=1022; c clob; procedure printout (p_clob in out nocopy clob) is offset number := 1; amount number := 32767; amount_last number := 0; len number := dbms_lob.getlength(p_clob); lc_buffer varchar2(32767); line_seq pls_integer := 1; -- For UNIX type file - replace CHR(13) to NULL CR char := chr(13); --CR char := NULL; LF char := chr(10);
nCRLF number; sCRLF varchar2(2); b_finish boolean := true; begin sCRLF := CR || LF; nCRLF := Length(sCRLF); if ( dbms_lob.isopen(p_clob) != 1 ) then dbms_lob.open(p_clob, 0); end if; amount := instr(p_clob, sCRLF, offset); while ( offset < len ) loop -- For without CR/LF on end file If amount < 0 then amount := len - offset + 1; b_finish := false; End If; dbms_lob.read(p_clob, amount, offset, lc_buffer); If b_finish then lc_buffer := SUBSTR(lc_buffer,1,Length(lc_buffer)-1);
End If; if (line_seq-1) > 0 then amount_last := amount_last + amount; offset := offset + amount; else amount_last := amount; offset := amount + nCRLF; end if; amount := instr(p_clob, sCRLF, offset); amount := amount - amount_last; dbms_output.put_line('Line #'||line_seq||': '||lc_buffer); line_seq := line_seq + 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 open c_clob; loop fetch c_clob into c; exit when c_clob%notfound; printout(c); end loop; close c_clob; end;

这里的行printout(c);(代码中的第4行)显示逐行数据blob数据直到缓冲区溢出。

预期结果:要从clob平面文件中读取数据并将列插入表格列中,我试图实现这一点。 约束是平面文件包含数百万条记录

1 个答案:

答案 0 :(得分:0)

我正在使用这样的东西

...
select * into ifile from clob_table where ...;
file_length  := dbms_lob.getlength (ifile.char_data);
p_start :=1;
while p_start<>0 loop
    end_pos := dbms_lob.instr (ifile.char_data, chr (10), p_start);
    if end_pos > 0 then
        strRow := dbms_lob.substr(ifile.char_data, least (end_pos - p_start, 240), p_start),chr (13)||chr (10);
        p_start := end_pos + 1;
        tabRow := strRow2tabRow(strRow);
    else
        strRow := dbms_lob.substr (ifile.char_data, file_length - p_start + 1,  p_start);
        p_start := 0;
        tabRow := strRow2tabRow(strRow);
    end if;

insert into myTable values tabRow;
end loop;
...

和功能

function strRow2tabRow(strRow varchar2) return myTable%rowtype is
    tabRow myTable%rowtype;
begin
    tabRow.col1:=valueIncolumn(strRow,1);
    tabRow.col2:=valueIncolumn(strRow,2);
    ...
    /*or maybe this may be better for you
    select * into tabRow from (
        select rownum rn, regexp_substr(strRow,'[^,]+', 1, level) hdn from dual connect by regexp_substr(strRow, '[^,]+', 1, level) is not null 
        ) pivot (max(hdn) for rn in (1, 2, ...));
    */      
    return tabRow;
exception when others then
    return tabRow;
end; 

function valueIncolumn(strRow varchar2, pos in number) return varchar2 is
    ret varchar2(1024);
begin
    select hdn into ret from (
        select rownum rn, regexp_substr(strRow,'[^,]+', 1, level) hdn from dual connect by regexp_substr(strRow, '[^,]+', 1, level) is not null 
    ) where rownum=pos;
    return ret;
exception when others then 
    return null;
end;     

希望有所帮助