Is there any better way to perform the UPDATE on a single table based on a resultset from multiple tables then the method given below.
The reason being, when join on tables with millions of records, it take more then 15 hours to update that one table for 46k records that matches with a resultset from join of multiple tables each with millions of records.
Would appreciate your advice.
SQL> Create table t1(a number, b number, w varchar2(10));
SQL> Create table t2(a number, b number, x varchar2(10));
SQL> Create table t3(a number, b number, y varchar2(10));
SQL> Create table t4(a number, b number, z varchar2(10));
SQL> Create table t5(a number, b number, w varchar2(10), x varchar2(10), y varchar2(10), z varchar2(10));
SQL> Insert into t1(a,b,w) values (1, 11, 't1');
SQL> Insert into t1(a,b,w) values (2, 22, 't1');
SQL> Insert into t1(a,b,w) values (3, 33, 't1');
SQL> Insert into t1(a,b,w) values (4, 44, 't1');
SQL> Insert into t1(a,b,w) values (5, 55, 't1');
SQL> Insert into t1(a,b,w) values (6, 66, 't1');
SQL> Insert into t1(a,b,w) values (7, 77, 't1');
SQL> Insert into t1(a,b,w) values (8, 88, 't1');
SQL> Insert into t2(a,b,x) values (1, 11, 't2');
SQL> Insert into t2(a,b,x) values (2, 22, 't2');
SQL> Insert into t2(a,b,x) values (3, 33, 't2');
SQL> Insert into t2(a,b,x) values (4, 44, 't2');
SQL> Insert into t2(a,b,x) values (5, 55, 't2');
SQL> Insert into t2(a,b,x) values (6, 66, 't2');
SQL> Insert into t3(a,b,y) values (1, 11, 't3');
SQL> Insert into t3(a,b,y) values (2, 22, 't3');
SQL> Insert into t3(a,b,y) values (3, 33, 't3');
SQL> Insert into t3(a,b,y) values (4, 44, 't3');
SQL> Insert into t4(a,b,z) values (1, 11, 't4');
SQL> Insert into t4(a,b,z) values (2, 22, 't4');
SQL> Select * from t1;
A B W
---------- ---------- ----------
1 11 t1
2 22 t1
3 33 t1
4 44 t1
5 55 t1
6 66 t1
7 77 t1
8 88 t1
8 rows selected.
SQL> Select * from t2;
A B X
---------- ---------- ----------
1 11 t2
2 22 t2
3 33 t2
4 44 t2
5 55 t2
6 66 t2
6 rows selected.
SQL> Select * from t3;
A B Y
---------- ---------- ----------
1 11 t3
2 22 t3
3 33 t3
4 44 t3
SQL> Select * from t4;
A B Z
---------- ---------- ----------
1 11 t4
2 22 t4
SQL> Select t1.a, t1.b, t1.w, t2.x, t3.y, t4.z
2 From t1, t2, t3, t4
3 Where t1.a = t2.a
4 And t1.b = t2.b
5 And t1.a = t3.a
6 And t1.b = t3.b
7 And t1.a = t4.a
8 And t1.b = t4.b;
A B W X Y Z
---------- ---------- -- -- -- --
1 11 t1 t2 t3 t4
2 22 t1 t2 t3 t4
SQL> Insert /*+ APPEND */ into t5 (a, b, w, x, y, z)
2 Select t1.a, t1.b, t1.w, t2.x, t3.y, t4.z
3 From t1, t2, t3, t4
4 Where t1.a = t2.a
5 And t1.b = t2.b
6 And t1.a = t3.a
7 And t1.b = t3.b
8 And t1.a = t4.a
9 And t1.b = t4.b;
2 rows created.
SQL> commit;
SQL> Select * from t5;
A B W X Y Z
---------- ---------- -- -- -- --
1 11 t1 t2 t3 t4
2 22 t1 t2 t3 t4
SQL> Select * from t1 Where a=1 and b=11;
A B W
---------- ---------- ----------
1 11 t1
SQL> Update t1 set w='v' Where a=1 and b=11;
1 row updated.
SQL> commit;
SQL> Select * from t1 Where a=1 and b=11;
A B W
---------- ---------- ----------
1 11 v
SQL> Declare
2
3 v_ucnt number := 0;
4 v_uget boolean := false;
5
6 Begin
7 For x in (Select t1.a, t1.b, t1.w, t2.x, t3.y, t4.z
8 From t1, t2, t3, t4
9 Where t1.a = t2.a
10 And t1.b = t2.b
11 And t1.a = t3.a
12 And t1.b = t3.b
13 And t1.a = t4.a
14 And t1.b = t4.b)
15 Loop
16 v_uget :=true;
17 Update t5 y
18 Set y.a = x.a,
19 y.b = x.b,
20 y.w = x.w,
21 y.x = x.x,
22 y.y = x.y,
23 y.z = x.z
24 Where y.a = x.a
25 And y.b = x.b;
26 v_ucnt := v_ucnt+1;
27 End Loop;
28 commit;
29 If ( NOT v_uget ) then
30 raise NO_DATA_FOUND;
31 End If;
32 dbms_output.put_line( 'No of Rows Updated in Table t5: ' || v_ucnt );
33 End;
34 /
No of Rows Updated in Table t5: 2
PL/SQL procedure successfully completed.
SQL> Select * from t5;
A B W X Y Z
---------- ---------- -- -- -- --
1 11 v t2 t3 t4
2 22 t1 t2 t3 t4
February 17, 2005 - 7:43 am UTC
in 8i/9i -- i would:
create global temporary table gtt( a,b,w,x,y,z, primary key(a,b) );
once in my database, then to update:
insert into gtt select t1.a, .......;
update ( select gtt.w new_w, gtt.x new_x, gtt.y new_y, gtt.z new_z,
t5.w old_w, t5.x old_x, t5.y old_y, t5.z old_z
from gtt, t5
where gtt.a = t5.a and gtt.b = t5.b )
set old_w = new_w, old_x = new_x, ......;
sql%rowcount has the rows updated.
(note: updating a, b is pointless...)
In 10g I would:
update t5
using ( select ........... ) x
on ( t5.a = x.a and t5.b = x.b )
when matched then update set x = x.x, y = x.y, .....;
no gtt needed.
No procedural code in any case.