Skip to Main Content
  • Questions
  • How to update millions of records on one table which column value comes from another one

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Joe.

Asked: February 18, 2016 - 8:16 am UTC

Last updated: February 18, 2016 - 12:48 pm UTC

Version: 11.2.0.4

Viewed 1000+ times

You Asked

Hi, Tom
I need your expertise in this regard. I got 2 tables which contains millions or records. If some certain column is equal (for example, column "id"), then change the target column value of one table to the other one.
For example:

SQL> desc tab1
Name Null? Type
------------------ -------- ----------------------
id NUMBER
new_column NUMBER

SQL> desc tab2
Name Null? Type
------------------ -------- ----------------------
id NUMBER
name NUMBER

I mean we want to change the value of "tab1.new_column" to "tab2.name", if "tab1.id" equals to "tab2.id".
I've tried this, but not quick enough.
SQL> declare
2 CURSOR cur IS
3 select tab2.id,tab2.name
4 from tab1
5 left join tab2 on tab1.id=tab2.id;
6 begin
7 FOR everyRow IN cur
8 loop
9 update tab1
10 set tab1.new_column = everyRow.name
11 where
12 tab1.id = tab2.id;
13 end loop;
14 commit;
15 end;
16 /

What would you likely to do?
Any suggestions please ! ! !

and Connor said...

When you need to update LOTS of data, it can often be quicker to create a new table with the results you require, eg

create table NEW_T
as
select tab1.id,tab2.name new_column
from tab1
left join tab2 on tab1.id=tab2.id;

because you can then run it in parallel to use all of the available server resources.

If that's not possible, consider a MERGE

merge into tab1
using ( select id, name from tab2 ) tab2
on (tab1.id = tab2.id )
when matched then set tab1.new_column = tab2.name

But since you used the term "new_column", if you are updating a *new* column in the table (that was originally null), then you are making every row that little bit bigger...which might cause problems down the track (google: oracle row chaining)

In that case, the create-table option is probably your best bet.

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Joe Huang, February 18, 2016 - 9:44 am UTC

Thanks Connor,
It really helps. It is quite a great idea that run a CREATE NEW TABLE with PARALLEL option. But it seems to a fly in the ointment, bcoz it is not a "zero-downtime" method. Maybe I just can't have my cake and eat it too. ^-^
Thanks a lot!
Connor McDonald
February 18, 2016 - 12:48 pm UTC

In that case, just be careful when you do that MERGE - because you'll lock all of the rows, which isn't much different.

In that instance, modify your PLSQL program to do FORALL so that you are updating in (say) batches of 1000.

See http://www.oracle.com/technetwork/issue-archive/2012/12-sep/o52plsql-1709862.html for some examples.