Unix Technical Forum

Using UPDATE with ROWNUM?

This is a discussion on Using UPDATE with ROWNUM? within the Oracle Database forums, part of the Database Server Software category; --> Hi, I have a production tablespace with millions of rows. I need to set sequence values in each row ...


Go Back   Unix Technical Forum > Database Server Software > Oracle Database

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-26-2008, 07:32 AM
darrenk@yahoo.com
 
Posts: n/a
Default Using UPDATE with ROWNUM?

Hi,
I have a production tablespace with millions of rows.
I need to set sequence values in each row but I can not lock the table
for any more than 5 seconds.
I created SEQUENCE named tempseq and found that I can update 1000 rows
in a short enough time.

Here is the script I tested. I have tested it but I don't understand
how each row (from the SELECT) is getting processed only once, or if
this script even guarantees that this will happen.

If someone can explain how ROWNUM is working in this UPDATE then that
would help me.
Alternative solutions (that don't involve explicit cursors) are also
welcome.

begin
loop
update (select seq_no from mytable) set seq_no = tempseq.nextval
where rownum <= 1000;
exit when SQL%FOUND = false;
commit;
end loop;
end;


TIA
-Darren

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 02-26-2008, 07:32 AM
Chris L.
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

On 26 jun, 12:54, darr...@yahoo.com wrote:
> Hi,
> I have a production tablespace with millions of rows.
> I need to set sequence values in each row but I can not lock the table
> for any more than 5 seconds.
> I created SEQUENCE named tempseq and found that I can update 1000 rows
> in a short enough time.
>
> Here is the script I tested. I have tested it but I don't understand
> how each row (from the SELECT) is getting processed only once, or if
> this script even guarantees that this will happen.
>
> If someone can explain how ROWNUM is working in this UPDATE then that
> would help me.
> Alternative solutions (that don't involve explicit cursors) are also
> welcome.
>
> begin
> loop
> update (select seq_no from mytable) set seq_no = tempseq.nextval
> where rownum <= 1000;
> exit when SQL%FOUND = false;
> commit;
> end loop;
> end;
>
> TIA
> -Darren


You need to include some condition to assure the update affects "un-
updated" rows only.

as in

update (etc)
set seq_no = (etc) where rownum <= 1000
and seq_no is null;

This way the next update will affect the next 1000 rows and so on.

But make sure to look up "bulk collect" and "forall" updating
examples, which D. Morgan of this same newsgroup recently pointed me
to! Much higher performance.


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 02-26-2008, 07:32 AM
darrenk@yahoo.com
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

> But make sure to look up "bulkcollect" and "forall" updating
> examples, which D. Morgan of this same newsgroup recently pointed me
> to! Much higher performance.


TYVM. Useful information for more that just this case!

This post has an example of bulk collect from a sequence (through a
dummy table):
http://groups.google.com/group/comp.... fec1f853a5501
Is this a reasonably efficient method? I probably want to bulk collect
about 1000 values at a time.

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 02-26-2008, 07:32 AM
Chris L.
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

On 26 jun, 14:56, darr...@yahoo.com wrote:
> > But make sure to look up "bulkcollect" and "forall" updating
> > examples, which D. Morgan of this same newsgroup recently pointed me
> > to! Much higher performance.

>
> TYVM. Useful information for more that just this case!
>
> This post has an example of bulk collect from a sequence (through a
> dummy table):http://groups.google.com/group/comp....rver/browse_th...
> Is this a reasonably efficient method? I probably want to bulk collect
> about 1000 values at a time.


You don't need to bulk collect from the sequence. I suggest you bulk
collect the primary key of the table being updated.

Then, using FORALL, you update the records with the sequence's
nextval.

As follows (example modified from D. Morgan's page)

CREATE TABLE parent (part_num NUMBER, part_name VARCHAR2(10),seq_no
number);
ALTER TABLE parent ADD PRIMARY KEY (part_num,part_name);

INSERT INTO parent (part_num,part_name)
SELECT 1,'a' FROM dual UNION
SELECT 2,'b' FROM dual UNION
SELECT 3,'c' FROM dual UNION
SELECT 4,'d' FROM dual ;

declare
TYPE array_one IS TABLE OF parent.part_num%TYPE;
TYPE array_two IS TABLE OF parent.part_name%TYPE;
tbl_num array_one;
tbl_name array_two;

CURSOR r IS
SELECT part_num,part_name
FROM parent;

BEGIN
OPEN r;
LOOP
FETCH r BULK COLLECT INTO tbl_num,tbl_name LIMIT 1000;

FORALL i IN 1..tbl_num.COUNT
UPDATE parent SET seq_no=tempseq.NEXTVAL
WHERE part_num=tbl_num(i)
AND part_name=tbl_name(i);

EXIT WHEN r%NOTFOUND;
END LOOP;
COMMIT;
CLOSE r;
END ;
/

(remember, I didn't know about bulk collect three days ago, so you
might want to look it up some more in the manual)

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 02-26-2008, 07:33 AM
Jagjeet Singh
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?


Bulk collect would be usefull if we are upding records one by one
through a loop
where we spent time in switch over from sql eng. to plsql. eng. But
here we can do this
directly through one update.

Let see if someone else can put more info, how bulk collect would be
usefull.


Regards,
Jagjeet Singh.

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 02-26-2008, 07:33 AM
Chris L.
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

On 26 jun, 17:11, Jagjeet Singh <jagjeet.ma...@gmail.com> wrote:
> Bulk collect would be usefull if we are upding records one by one
> through a loop
> where we spent time in switch over from sql eng. to plsql. eng. But
> here we can do this
> directly through one update.
>
> Let see if someone else can put more info, how bulk collect would be
> usefull.
>
> Regards,
> Jagjeet Singh.


According to the original poster, using only one update would lock the
table for too long. He determined that updating 1000 rows at a time
resulted in a short-enough lock.

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 02-26-2008, 07:33 AM
Jagjeet Singh
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

begin
loop
update table set col1 = sequence.nextval where col1 is null and rownum
< 1001;
commit;
end loop;
end;

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 02-26-2008, 07:33 AM
unladen.sparrow@gmail.com
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

On Jun 26, 2:57 pm, "Chris L." <diver...@uol.com.ar> wrote:
> You don't need to bulk collect from the sequence. I suggest you bulk
> collect the primary key of the table being updated.
>
> Then, using FORALL, you update the records with the sequence's
> nextval.
>
> As follows (example modified from D. Morgan's page)
>
> CREATE TABLE parent (part_num NUMBER, part_name VARCHAR2(10),seq_no
> number);
> ALTER TABLE parent ADD PRIMARY KEY (part_num,part_name);
>
> INSERT INTO parent (part_num,part_name)
> SELECT 1,'a' FROM dual UNION
> SELECT 2,'b' FROM dual UNION
> SELECT 3,'c' FROM dual UNION
> SELECT 4,'d' FROM dual ;
>
> declare
> TYPE array_one IS TABLE OF parent.part_num%TYPE;
> TYPE array_two IS TABLE OF parent.part_name%TYPE;
> tbl_num array_one;
> tbl_name array_two;
>
> CURSOR r IS
> SELECT part_num,part_name
> FROM parent;
>
> BEGIN
> OPEN r;
> LOOP
> FETCH r BULK COLLECT INTO tbl_num,tbl_name LIMIT 1000;
>
> FORALL i IN 1..tbl_num.COUNT
> UPDATE parent SET seq_no=tempseq.NEXTVAL
> WHERE part_num=tbl_num(i)
> AND part_name=tbl_name(i);
>
> EXIT WHEN r%NOTFOUND;
> END LOOP;
> COMMIT;
> CLOSE r;
> END ;
> /


This works great. Much faster than my original script.
Thanks.

> (remember, I didn't know about bulk collect three days ago, so you
> might want to look it up some more in the manual)

This example is as good as any from the manual.

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9 (permalink)  
Old 02-26-2008, 07:33 AM
DA Morgan
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

Jagjeet Singh wrote:
> begin
> loop
> update table set col1 = sequence.nextval where col1 is null and rownum
> < 1001;
> commit;
> end loop;
> end;
>


I don't know what this is other than one of the worst examples of PL/SQL
I have seen in a very long time. And I teach students new to PL/SQL.
--
Daniel A. Morgan
University of Washington
damorgan@x.washington.edu (replace x with u to respond)
Puget Sound Oracle Users Group
www.psoug.org
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10 (permalink)  
Old 02-26-2008, 07:34 AM
Jagjeet Singh
 
Posts: n/a
Default Re: Using UPDATE with ROWNUM?

> I don't know what this is other than one of the worst examples of PL/SQL
> I have seen in a very long time. And I teach students new to PL/SQL.


what other way you can suggest ?

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 03:20 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
www.UnixAdminTalk.com