我在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平面文件中读取数据并将列插入表格列中,我试图实现这一点。 约束是平面文件包含数百万条记录。
答案 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;
希望有所帮助