Reputation: 67
I have a temp table(around 760k rows ) with no primary key. i am trying to insert rows from this temp table to my main table using bulk collect and forall(also used save exceptions to catch the rejected rows) , i have successfully done this. But i need to keep track of rows which are getting rejected and which are moved succesfully(what i want to do is update status column of temp table as 'E' for error and M for succeeful migration) here is my procedure:
code snippet
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;
In above code i am updating the row which went into a exception part as 'E' but for the row which is inserting succesfully iam unable to update the status , primarily i need to catch that rownum or rowid to update which iam unable to get from for all how to update the succefully moved row? please help me out thanks in advance..
Upvotes: 1
Views: 2822
Reputation: 67762
You approach is quite clever but there are a few things that won't work properly:
l_tab
nested table in the exception block, so it's easy to pick the relevant id
or rowid
.My advice would be to fetch the rowid at the same time as the rest of the data:
CURSOR c_data IS
SELECT temp_table.*, a.*, temp_table.rowid rid
FROM temp_table, a
WHERE temp_table.col1 = a.col;
Then in the exception block you could find and update the offending row:
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;
Upvotes: 2