我有一个没有主键的临时表(大约760k行)。我试图使用批量收集和forall(也使用保存异常来捕获被拒绝的行)将此临时表中的行插入到我的主表中,我已成功完成此操作。但我需要跟踪被拒绝的行以及成功移动的行(我想要做的是将临时表的状态列更新为错误的“E”和成功迁移的M) 这是我的程序:
代码段
desc temp_table:
col1 varchar2(30);
col2 varchar2(30);
col3 number;
col4 number;
status varchar2(1);
create or replace procedure mov_to_main_table
as
loop_count number default 0;
error_row_no number default 0;
sql_stmt varchar2(500);
cursor c_data is
select * from temp_table,a
where temp_table.col1=a.col;
TYPE t_bulk_collect_tab IS TABLE OF c_data%ROWTYPE;
l_tab t_bulk_collect_tab;
l_inserted t_bulk_collect_tab;
BEGIN
OPEN c_data;
LOOP
FETCH c_data
BULK COLLECT INTO l_tab LIMIT 1000;
EXIT WHEN l_tab.count = 0;
BEGIN
FORALL i IN 1..l_tab.count save exceptions
insert into main_table(col1,col2,col3)
values(l_tab(i).col1,l_tab(i).col2,l_tab(i),col3);
EXCEPTION
when others then
bulk_error_count := sql%bulk_exceptions.count;
--dbms_output.put_line('number of error rows :'||bulk_error_count );
for i in 1..bulk_error_count
loop
error_row_no := to_number(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX)+100*loop_count;
sql_stmt := 'update temp_table set status=''E'' where rowid in (select rowid from temp_table where rownum <=:1 minus select rowid from temp_table where rownum<:2)';
execute immediate sql_stmt using error_row_no,error_row_no;
end loop;
end;
在上面的代码中,我将更新进入异常部分的行作为“E” 但对于成功插入的行,我无法更新状态, 主要是我需要抓住那个rownum或rowid来更新哪个iam无法从中获取 如何更新成功移动的行? 请帮帮我 提前谢谢..
答案 0 :(得分:2)
你的做法非常聪明,但有些事情无法正常运作:
l_tab
嵌套表格,因此您可以轻松选择相关的id
或rowid
。我的建议是在与其他数据同时获取rowid:
CURSOR c_data IS
SELECT temp_table.*, a.*, temp_table.rowid rid
FROM temp_table, a
WHERE temp_table.col1 = a.col;
然后在异常块中,您可以找到并更新有问题的行:
EXCEPTION
WHEN OTHERS THEN
bulk_error_count := SQL%bulk_exceptions.count;
--dbms_output.put_line('number of error rows :'||bulk_error_count );
FOR i IN 1 .. bulk_error_count LOOP
UPDATE temp_table
SET status = 'E'
WHERE rowid = l_tab(SQL%BULK_EXCEPTIONS(i).error_index).rid);
END LOOP;
END;