问题描述
我需要获取既将csv数据写入文件,又用同一记录更新表的数据。该光标可能会找到10万至30万条记录。
有没有比循环更有效的方法呢?我当时想在循环外使用Select进行插入,但是无法知道每条记录是否已成功写入文件。
DECLARE
...
file_output VARCHAR2 (3000);
col2 column2%type;
col3 column3%type;
CURSOR my_cursor
IS
select
csv_val1 || ',' || csv_val2|| ',' || csv_val3,column2,column3
from my_cursor_table
...
BEGIN
...
FETCH my_cursor INTO file_output,col2,col3;
WHILE my_cursor%FOUND
LOOP
BEGIN
UTL_FILE.PUT_LINE (ID,file_output);
insert into my_insert_table values(col2,col3);
..
END;
解决方法
您可以:
-
bulk collect
将查询放入具有限制的数组中 - 遍历数组,将每个元素写入文件
- 将
utl_file
调用包装在记录错误并从数组中删除该元素的异常处理程序中。 - 使用
forall i in indices of
仅插入成功的值
这应该比单行处理更快。在这个简单的示例中,处理了10万行:
- 逐行处理约为15秒
- 批量收集/永久保存约1.5秒
所以快10倍左右:
create table t (
c1 int,c2 int
);
set timing on
declare
cursor cur is
select level c1,mod ( level,10 ) c2
from dual
connect by level <= 100000;
rec cur%rowtype;
f utl_file.file_type;
begin
f := utl_file.fopen ('TMP','test.csv','w');
open cur;
loop
fetch cur into rec;
exit when cur%notfound;
begin
utl_file.put_line ( f,rec.c1 || ',' || rec.c2 );
insert into t values ( rec.c1,rec.c2 );
exception
when others then
dbms_output.put_line( 'Error logging' );
end;
end loop;
close cur;
utl_file.fclose(f);
end;
/
PL/SQL procedure successfully completed.
Elapsed: 00:00:15.192
declare
cursor cur is
select level c1,10 ) c2
from dual
connect by level <= 100000;
type rec_arr is table of cur%rowtype
index by pls_integer;
rec rec_arr;
f utl_file.file_type;
begin
f := utl_file.fopen ('TMP','w');
open cur;
loop
fetch cur bulk collect into rec
limit 100;
exit when rec.count = 0;
for i in 1 .. rec.count loop
begin
utl_file.put_line ( f,rec(i).c1 || ',' || rec(i).c2 );
exception
when others then
dbms_output.put_line( 'Error logging' );
rec.delete(i);
end;
end loop;
forall i in indices of rec
insert into t values ( rec(i).c1,rec(i).c2 );
end loop;
close cur;
utl_file.fclose(f);
end;
/
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.578
请注意,这无法处理写入成功但插入失败的情况...
要解决此问题,您可以执行以下操作:
- 插入行(使用
forall ... save exceptions
或insert ... log errors
) - 写成功的行
- 删除未能写入文件的行