I hope I understood correctly your predicament, although it is possible I might miss something. If I got your idea correctly, you want to operate over a set of tables and generate the records to delete and the ones to insert based on the minus-two-way.
I would go for global temporary tables, using commit on preserve rows, but I would centralize the code in a procedure
First a control table
create table control_process
( id_time timestamp default systimestamp ,
source_table varchar2(128),
source_view varchar2(128),
rows_processed number,
exit_code number,
error_message varchar2(400)
);
Procedure for GTTs using input parameters table and view
It is very important that you adapt the code below to your needs:
- If the columns in the table and view are not the same, you must adapt the query behind the GTT creation to use whatever is necessary. If you want to do it dynamically, you must create another cursor to match the columns between the table and view used as input parameter.
- In order to delete/insert you have to compare the GTT with the original table. That is why I have the cursor with the columns that I use to create the dynamic construction, both for insert and delete.
- I did not have a place to verify the code, so please be aware that could be typos or errors on it.
- The control table is optional, but allows you to have a kind of place where you stored the results for each table/view
- This solution allows you to use it for all the tables and views in one single place.
- the
materialize hint will help you as you read once the view and the table in the construction of the minus-two-way.
Having said that, that could be an approach ( you have to adapt it to your needs )
create or replace procedure pr_generate_rows ( psourcetable in varchar2 , psourceview in varchar2 )
is
vddl clob;
vdml clob;
vsql clob;
vcode pls_integer;
verrm varchar2(300);
out_string varchar2(128);
cursor c_tab_columns
is
select column_name, count(*) over () tot_rows
from all_tab_columns where table_name = psourcetable and owner = 'MY_SCHEMA'
order by column_id;
begin
vddl := ' create global temporary table gtt_'||psourcetable||' on commit preserve rows
as
with x
as
( select /*+materialize */ * from '||psourceview||'
),
y as
( select /*+materialize */ * from '||psourcetable||'
)
select * from (
select ''INSERT'' as mode, a.* from
(
select ... from x
MINUS
select ... from y
) a
UNION ALL
select ''DELETE'' as mode, b.* from (
select ... from y
MINUS
select ... from x ) b
)
' ;
execute immediate vddl;
vdml := ' insert into control_process ( source_table, source_view , rows_processed , exit_code )
select '''||psourcetable||''' as source_table ,
'''||psourceview||''' as source_view ,
( select count(*) from gtt_'||psourcetable||' ) as rows_processed ,
0 as exit_code from dual
' ;
execute immediate vdml ;
-- Perform Insert and Delete over final table
-- Delete
vsql := ' delete from '||psourcetable||'
where exists
( select 1 from gtt_'||psourcetable||' a join '||psourcetable||' b
on ( ';
for item in c_tab_columns
loop
out_string := item.COLUMN_NAME;
if c_tab_columns%rowcount = 1
then
vexpression := ' a.'||out_string||' = b.'||out_string||' and ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
elsif c_tab_columns%rowcount < item.tot_rows then
vexpression := ' a.'||out_string||' = b.'||out_string||' and ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
else
vexpression := ' a.'||out_string||' = b.'||out_string||' ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
end if;
end loop;
dbms_lob.append ( vsql, ')' );
dbms_lob.append(vsql,''||chr(10)||'');
dbms_lob.append ( vsql, ' where a.mode = ''DELETE'' ');
dbms_lob.append ( vsql, ' ) ');
execute immediate vsql;
-- Insert
vsql := ' insert /*+ append */ into '||psourcetable||' a
select ' ;
for item in c_tab_columns
loop
out_string := item.COLUMN_NAME;
if c_tab_columns%rowcount = 1
then
vexpression := ' b.'||out_string||' , ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
elsif c_tab_columns%rowcount < item.tot_rows then
vexpression := ' b.'||out_string||' , ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
else
vexpression := ' b.'||out_string||' ' ;
dbms_lob.append(vsql,vexpression);
dbms_lob.append(vsql,''||chr(10)||'');
end if;
end loop;
dbms_lob.append(vsql,'from gtt_'||psourcetable||' b where b.mode = ''INSERT'' ');
execute immediate vsql;
exception
when others then
vcode := sqlcode;
verrm := substr(sqlerrm, 1, 300);
vdml := ' insert into control_process ( source_table, source_view , rows_processed , exit_code , error_message )
values (
'''||psourcetable||''' ,
'''||psourceview||''' ,
0,
vcode,
'''||verrm||'''
) ' ;
execute immediate vdml;
commit;
raise;
end;
/
Any questions, let me know.