sure, here is an example:
ops$tkyte@ORA817DEV> create table t
2 as
3 select username, user_id, created
4 from all_users;
Table created.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> alter table t add constraint t_pk primary key(user_id);
Table altered.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> create table stage
2 as
3 select lower(username) username, user_id, created, 'U' dml_type
4 from all_users
5 where mod(user_id,2) = 1
6 /
Table created.
ops$tkyte@ORA817DEV> insert into stage
2 select 'X'||username, -(user_id-1), created, 'I' dml_type
3 from all_users
4 /
56 rows created.
ops$tkyte@ORA817DEV> insert into stage
2 select username, user_id, created, 'D' dml_type
3 from all_users
4 where mod(user_id,2) = 0
5 /
27 rows created.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> alter table stage add constraint stage_pk primary key(user_id);
Table altered.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> create or replace procedure p ( p_str in varchar2 )
2 is
3 l_str long := p_str;
4 begin
5 dbms_output.put_line( '---------------' );
6 loop
7 exit when l_str is null;
8 dbms_output.put_line( substr( l_str, 1, 250 ) );
9 l_str := substr( l_str, 251 );
10 end loop;
11 dbms_output.put_line( '---------------' );
12 end;
13 /
Procedure created.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> create or replace procedure sync_em_up( p_tname in varchar2, p_stage in varchar2 )
2 as
3 l_cnames dbms_sql.varchar2_table;
4 l_cnames_pk dbms_sql.number_table;
5 l_cnames_csv long;
6 l_pknames_csv long;
7 l_stmt long;
8 begin
9 select user_tab_columns.column_name,
10 decode(user_cons_columns.column_name,NULL,0,1)
11 BULK COLLECT into l_cnames, l_cnames_pk
12 from user_tab_columns,
13 (select column_name
14 from user_cons_columns
15 where constraint_name =
16 ( select constraint_name
17 from user_constraints
18 where table_name = upper(p_tname)
19 and constraint_type = 'P' )
20 ) user_cons_columns
21 where user_tab_columns.table_name = upper(p_tname)
22 and user_tab_columns.column_name = user_cons_columns.column_name(+)
23 order by user_tab_columns.column_id;
24
25 for i in 1 .. l_cnames.count
26 loop
27 l_cnames_csv := l_cnames_csv || l_cnames(i) || ', ';
28 if ( l_cnames_pk(i) = 1 )
29 then
30 l_pknames_csv := l_pknames_csv || l_cnames(i) || ', ';
31 end if;
32 end loop;
33 l_cnames_csv := rtrim(rtrim(l_cnames_csv),',');
34 l_pknames_csv := rtrim(rtrim(l_pknames_csv),',');
35
36 l_stmt := 'delete from ' || p_tname ||
37 ' where ( ' || l_pknames_csv ||
38 ' ) in ( select ' || l_pknames_csv ||
39 ' from ' || p_stage || ' where dml_type = ''D'' )';
40
41 p(l_stmt);
42 execute immediate l_stmt;
43
44
45 l_stmt := 'update ( select ';
46 for i in 1 .. l_cnames.count
47 loop
48 l_stmt := l_stmt || ' a.' || l_cnames(i) || ' A' || i ||
49 ', b.' || l_cnames(i) || ' B' || i || ',';
50 end loop;
51 l_stmt := rtrim(l_stmt, ',' ) || ' from ' || p_tname ||
52 ' a, ' || p_stage || ' b ' ||
53 ' where b.dml_type = ''U'' ';
54 for i in 1 .. l_cnames.count
55 loop
56 if ( l_cnames_pk(i) = 1 )
57 then
58 l_stmt := l_stmt || ' and a.' || l_cnames(i) ||
59 ' = b.' || l_cnames(i);
60 end if;
61 end loop;
62 l_stmt := l_stmt || ' ) set ';
63 for i in 1 .. l_cnames.count
64 loop
65 if ( l_cnames_pk(i) = 0 )
66 then
67 l_stmt := l_stmt || ' A' || i || ' = ' ||
68 ' B' || i || ',';
69 end if;
70 end loop;
71 l_stmt := rtrim(l_stmt,',');
72
73 p(l_stmt);
74 execute immediate l_stmt;
75
76 l_stmt := 'insert into ' || p_tname ||
77 '( ' || l_cnames_csv || ' ) ' ||
78 'select ' || l_cnames_csv ||
79 ' from ' || p_stage ||
80 ' where dml_type = ''I'' ';
81
82 p(l_stmt);
83 execute immediate l_stmt;
84 end;
85 /
Procedure created.
ops$tkyte@ORA817DEV>
ops$tkyte@ORA817DEV> exec sync_em_up( 't', 'stage' );
---------------
delete from t where ( USER_ID ) in ( select USER_ID from stage where dml_type = 'D' )
---------------
---------------
update ( select a.USERNAME A1, b.USERNAME B1, a.USER_ID A2, b.USER_ID B2, a.CREATED A3, b.CREATED B3 from t a, stage b where
b.dml_type = 'U' and a.USER_ID = b.USER_ID ) set A1 = B1, A3 = B3
---------------
---------------
insert into t( USERNAME, USER_ID, CREATED ) select USERNAME, USER_ID, CREATED from stage where dml_type = 'I'
---------------
PL/SQL procedure successfully completed.
ops$tkyte@ORA817DEV>