Home » SQL & PL/SQL » SQL & PL/SQL » need some help with PL/SQL
need some help with PL/SQL [message #9557] Wed, 19 November 2003 08:19 Go to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
I'm trying to write this PL/SQL code that will go through the records of a table and delete the records with a certain condition...also doing a save after every 100. When I run this code below it works but crashes my sql+ which is a cause for concern for me...I guess the way I have the code below must be filling up some sort of buffer...and my committ for every 100 must not be helping..cna anyone offer any advice for help on how I can prevent the sql+ from crashing..

I thought this would have been right :

Declare

v_id varchar2(8);
v_count number(8);

cursor v_cursor is

select name_id from record_table;

begin

v_count := 0;

open v_cursor;
loop

fetch v_cursor into v_id;
exit when v_cursor%notfound;

delete from record_table
where userid = 'admin3';

v_count := v_count + 1;

if v_count = 100 then
commit;
v_count := 0;
end if;

end loop;
close v_cursor;
commit;

end;
/
Re: need some help with PL/SQL [message #9558 is a reply to message #9557] Wed, 19 November 2003 08:34 Go to previous messageGo to next message
Art Metzer
Messages: 2480
Registered: December 2002
Senior Member
Andy,

No need for PL/SQL here, just use straight SQL:
DELETE FROM record_table WHERE userid = 'admin3';
COMMIT;
I would highly recommend to you the Ask Tom site, commonly referenced on this board, and at which Oracle guru Tom Kyte asks all ranges of Oracle questions. There is a ton of knowledge there.

For example, here are some drums he commonly beats that directly relate to your question:<ol>[*]The Tom Kyte mantra:
If you can do it in a single SQL statement -- do it.
If you cannot, do it in PL/SQL.
If you cannot, use a little Java stored procedure.
If that doesn't cut it, use a C external procedure.[*]COMMITing within a cursor loop (a no-no)</ol>Happy learning,

Art.
Hi Art [message #9559 is a reply to message #9558] Wed, 19 November 2003 08:45 Go to previous messageGo to next message
andy
Messages: 92
Registered: December 1999
Member
I wanted to do this with a single SQL statement originally but have been requested from Q/A that I am to use a Pl/SQL because there are over 1 million records in that table and to ensure that I am saving every 100 that get deleted in case there is a hiccup on the server.....

Can you help me with my PL/SQL code?

Thanks for yoru response
Re: Hi Art [message #9560 is a reply to message #9559] Wed, 19 November 2003 09:09 Go to previous messageGo to next message
Art Metzer
Messages: 2480
Registered: December 2002
Senior Member
Committing within a PL/SQL cursor loop is the wrong approach to this problem. If there's a "hiccup on the server", just re-issue the command. You're doing a DELETE on one table, what have you lost? And what does the PL/SQL approach buy you?

What error does your PL/SQL version crash with?

The DELETE will run so much faster in straight SQL. Can you benchmark both scenarios for your QA department in a test environment?

A.
Re: Hi Art [message #9561 is a reply to message #9560] Wed, 19 November 2003 09:16 Go to previous messageGo to next message
andy
Messages: 92
Registered: December 1999
Member
No errors show up it is just crashing...the sql+ program although when I look up the table after restarting sql+ I can see that my code works. I figure it has soemthing to do with the buffer.

Approaching the Q/A person (just a person not a department) can be a bit of a challenge...he is quite persistant on how he wants thinsg done...

I fully agree with you and originally was the way that I wanted to approach the task...

However my SQL liner was shot done and was told I was specifically told to save every 100 records...

I'm not sure I can set up a benchmark scenario but more then welcome any advice on your part....

I hate to say it but I'm not sure if i can convince the Q/A person even with proof...he is quite headstrong and hard to approach if he wants to be right even if he isn't ...(I'm sure we all have those around us don't we) ;-)
Re: Hi Art [message #9562 is a reply to message #9561] Wed, 19 November 2003 09:20 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
just curious but are there ways I cna get around this in pl/sql without a loop...therefore avoiding the commit in the loop?
Re: Mass delete [message #9563 is a reply to message #9562] Wed, 19 November 2003 10:55 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Outside of issues introducted by triggers or referential integrity, the only error you could have (in normal operation) would be that you have run out of rollback space for this operation.

The proper way to deal with this is to size your rollback segments properly for the types of transactions you do and issue the single delete as Art mentioned. If you need to delete 1M rows, and you do, the DBA needs to make your RBS bigger. RBS is not a scarce resource. If it is not sized properly, developers waste time writing workarounds that take longer to execute and consume more resources.

If you have no control over the RBS sizing, then here is an approach that avoids fetching across commits, but still takes longer than a single delete.

begin
  loop
    delete from record_table
     where userid = 'admin3'
       and rownum <= 50000;  -- make this as large as possible
    exit when sql%rowcount = 0;
    commit;
  end loop;
end;
Re: Mass delete [message #9564 is a reply to message #9563] Wed, 19 November 2003 11:10 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
Hi Todd

I think your right...thanks for the clue
ok so im lost again [message #9565 is a reply to message #9564] Wed, 19 November 2003 12:04 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
Talked to Q/A guy and was given a talk about how the commits are needed in the loops becuase of the sensitive information involved....he informed me that I do in fact need to use rownum and rowtype and save every 100 row num's....does this mean I shouldn't use my counter at all...I tried a few ideas with the latest one below but I think im way off...anyone have any advice...sorry about that

Declare
v_rownum number(10);
v_id varchar2(8);
v_count number(8);

cursor v_cursor is

select rownum,name_id from record_table
where userid = 'admin3';

begin

v_count := 0;

open v_cursor;
loop

fetch v_cursor into v_rownnum, v_id;
exit when v_cursor%notfound;

delete from record_table
here rownum = v_rownum;

v_count := v_count + 1;

if v_count = 100 then
commit;
v_count := 0;
end if;

end loop;
close v_cursor;
commit;

end;
/
Re: ok so im lost again [message #9566 is a reply to message #9565] Wed, 19 November 2003 12:28 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Andy, not to be indelicate, but your Q/A guy is full of it.
Re: ok so im lost again [message #9567 is a reply to message #9566] Wed, 19 November 2003 13:28 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
thanks Todd

no comment on my part in case he reads these boards (gulp) haha in which case im probably in huge trouble as it is ;-)
Re: ok so im lost again [message #9570 is a reply to message #9566] Wed, 19 November 2003 15:09 Go to previous messageGo to next message
sverch
Messages: 582
Registered: December 2000
Senior Member
Todd,
As always you got it right. I just wonder how people like this stay employed.
Re: ok so im lost again [message #9571 is a reply to message #9567] Wed, 19 November 2003 15:13 Go to previous messageGo to next message
sverch
Messages: 582
Registered: December 2000
Senior Member
You do not have to worry about it. People like him never read these boards.
P/S
Sorry, after the word "read" I had to place a period.
solved [message #9580 is a reply to message #9571] Fri, 21 November 2003 06:56 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
I finally got a workable solution using an example with

if (mod(c1%rowcount,1000)=0) then commit;

it worked well and all is well in the world :-)

back to my learning PL/SQL

so much to learn so little time..

thanks for the reference to ask tom Art..I am findingthe site very useful.
Re: solved [message #9585 is a reply to message #9580] Fri, 21 November 2003 10:36 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Andy:

Just for the record, you are fetching across a commit which is exactly what Art and I have recommended avoiding in our examples. You have opened up yourself to the possibility of ORA-01555 errors.

It is so frustrating to spend so much time answering questions and pointing people in the right direction, and they end up doing exactly what you recommend not to do...
Re: solved [message #9588 is a reply to message #9585] Fri, 21 November 2003 11:28 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
My apologies to you Todd and to Art if I offended at all. I certainly didn't mean to. And I have to say that I did learn by both your posts....I do appreciate your help very much.

I was basically given instructions on how I was to proceed and it was reallymy only option...

until I prove myself to be a stronger developer (which I'm working on) I'm afraid im behind the 8 ball in proving anyone in my work enviorment differently.

I know this won't help ....

I wrote my code and tested it in development under every single scenario very carefully I could have thought of.

It had worked and did not cause any ORA-01555 error.

The code was approved by Q/A....

I can only say that I am very sorry for causing you frustration. :-(

This is all new to me...I'm hoping to get better
Re: solved [message #9589 is a reply to message #9580] Fri, 21 November 2003 11:34 Go to previous messageGo to next message
Thiru
Messages: 1089
Registered: May 2002
Senior Member
You went back to where you started !

Apart from the Fetch across commit issue, you will need to understand the cost of a commit.

Everytime you commit , following things happen in the background :

i) the transaction table of the rollback segment needs to get updated with commit scn
ii) the rollback segment header needs to be updated with the information that its free now
iii) these rollback segment changes need to written to the online redolog files
iv) LGWR has to flush the redo entries from the redolog buffer cache into the redolog files
v) Commit confirmation is returned to the calling program.

And now you start another transaction , which undergoes additional overhead in allocating entries in rollback segments etc etc..do the processing and there comes another commit ,so soon ! It slows down the processing so much.

Size your rollback segments approprietly and do the DML in ONE SIMPLE SQL , whenever possible. You dont have to use PL/SQL just for the sake of using it.

-Thiru
Re: solved [message #9591 is a reply to message #9589] Fri, 21 November 2003 13:33 Go to previous messageGo to next message
Andy G
Messages: 25
Registered: May 2003
Junior Member
I have this printed and placed on the wall of my cubicle...thanks for the info
Re: no worries [message #9593 is a reply to message #9588] Fri, 21 November 2003 15:07 Go to previous message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Andy, no offense taken at all. I realize that sometimes there are constraints placed upon you that you do not have control over. As you continue to develop your skills, you will have more and more control over how things are done.

PL/SQL is a great language for data manipulation, but I only use the procedural elements of it (loops, etc.) when I cannot accomplish the task in a single SQL statement (or set of statements).
Previous Topic: Count Records Help
Next Topic: trigger help
Goto Forum:
  


Current Time: Mon Dec 23 03:32:56 CST 2024