Database Forum / Oracle / Oracle Server / December 2005
Very strange problem.
|
|
Thread rating:  |
Scarab - 28 Dec 2005 01:17 GMT Hi, Something strange happened to me:
declare v_rowid varchar(18); cursor icur is select rowid from itest where (idate < SYSDATE - 30); begin open icur; loop fetch icur into v_rowid; exit when icur%NOTFOUND; delete from itest where rowid = v_rowid; if (mod(icur%ROWCOUNT,3000) = 0) then commit; end if; end loop; close icur; commit; end;
I use the above sql to delete some data from table itest, but after execute the sql, I use select * from itest where (idate < SYSDATE - 30); There are still some records that not deleted. What's wrong? After running the SQL again and again, all the records can be deleted. By the way, table itest is accessed very frequently, updating and inserting all the time. Thanks.
Mark C. Stock - 28 Dec 2005 02:26 GMT > Hi, > Something strange happened to me: [quoted text clipped - 28 lines] > all the time. > Thanks. SYSDATE includes time to the seconds, if idate does too, then you have a moving target -- every iteration addresses a different time slice
++ mcs
Mark D Powell - 28 Dec 2005 02:51 GMT Scarab, I suspect your problem has to do with the fact that idate is an Oracle date datatype and as such it also includes time. That means your query does not affect all rows for a specific date, as in day of the month, the same since depending on when the query runs rows some rows for a day will test true and some will test false. That is if the query time is 9 AM then any row on the same day that has a time value greater than 9 AM will not be included in the result set.
Try where ( idate < trunc(sysdate - 30) )
This will treat all date values for the cutoff date the same, that is, time values of 00:00:00 - 23:59:59 will all test true in the where clause.
The other potential problem you have has to the with the Oracle read consistency model and how inserts, updates, and deletes are done in this table. It is not wise to use rowid values fetched in non-select for update cursors to peform update or delete operations if concurrent delete operations exist, without specifying additional selection criteria. User A selects a list of rows to be processed without locking them. User B deletes row 60 and commits. Now user B or C inserts a new row and commits. The space was available at rowid 60 so Oracle reuses it. Now session A gets around to rowid 60 and issues a delete by rowid. This is not the same row that was fetched by the driving cursor. Whenever concurrent deletes are possible then before doing a delete or update by rowid you should verify that the row still meets the selection criteria. In your example the idate would need to still be < trunc(sysdate) - 30. If on update or delete the additional criteria fails then no action is taken, that is, the delete or update would not affect any rows. This is not considered an error by Oracle and processing would continue.
HTH -- Mark D Powell --
Giridhar - 28 Dec 2005 05:19 GMT Hi, I have a doubt whether we can have a cursor on the table and open the cursor to delete data from the same table. Will it not cause "snapshot too old error" (1555 Error)?
Thanks, Giridhar Kodakalla
Scarab - 28 Dec 2005 06:53 GMT Giridhar, My Oracle is 8.1.7, I delete records according to rowid, It work for me. I recall your case is also possible, I have ever seen such a case, but the error message is not : snapshot too old error, but others which I can't remember.
Thanks
"Giridhar" <gkodakalla@gmail.com> wrote in message news:1135747171.889177.308550@o13g a 2000cwo.googlegroups.com...
> Hi, > I have a doubt whether we can have a cursor on the table and open the [quoted text clipped - 4 lines] > Thanks, > Giridhar Kodakalla Scarab - 28 Dec 2005 07:38 GMT OK, Thanks for your wonderful reply, that's the problem. And I have some other puzzles: Can I use "for update" in the declaration of a cursor? cursor icur is select rowid from itest where (idate < SYSDATE - 30) for update;
If it can: 1. it will only lock the records that fit the criteria and have nothing to do with the other records, is it right? 2. When I commit records after delete 3000 rows, if (mod(icur%ROWCOUNT,3000) = 0) then commit; The cursor is no longer usable because the commit operation, how to workaroud it?
Thank you very much.
> Giridhar, > My Oracle is 8.1.7, I delete records according to rowid, It work for me. I [quoted text clipped - 14 lines] > > Thanks, > > Giridhar Kodakalla Sybrand Bakker - 28 Dec 2005 09:06 GMT >OK, Thanks for your wonderful reply, that's the problem. >And I have some other puzzles: [quoted text clipped - 13 lines] > >Thank you very much. 1 Please stop top-posting. 2 for update is allowed in a cursor declaration 3 only affected records are locked 4 you don't need to commit in a loop. In Oracle 9i, just set your undo_retention_time appropiately. If this is a disk space issue, buy more disks.
-- Sybrand Bakker, Senior Oracle DBA
Scarab - 29 Dec 2005 03:14 GMT Thanks for your reply, here comes my sp:
create or replace procedure clitest as v_rowid varchar(18); msg varchar2(256); cursor icur is select rowid from itest where (idate < SYSDATE - 30) for update nowait; begin open icur; loop fetch icur into v_rowid; exit when icur%NOTFOUND; delete from itest where rowid = v_rowid ; if (mod(icur%ROWCOUNT,1000) = 0) then commit; end if; end loop; close icur; commit; exception when others then rollback; msg := 'err:'||substr(sqlerrm, 1, 90); insert into sm_err_msg(e_date, e_msg) values (sysdate, msg); commit; end;
Because the number of record is very large, so I want to commit every 1000 rows, but after commit for the first time, the cursor is not availible any more because of the for update clause in the cursor.
How to workaround it? Thanks.
> >OK, Thanks for your wonderful reply, that's the problem. > >And I have some other puzzles: [quoted text clipped - 23 lines] > -- > Sybrand Bakker, Senior Oracle DBA Sybrand Bakker - 29 Dec 2005 06:44 GMT >Because the number of record is very large, so I want to commit every 1000 >rows, but after commit for the first time, the cursor is not availible any >more because of the for update clause in the cursor. > >How to workaround it? Thanks. You didn't read my reply, did you? If so, why do you continue top-posting, and why don't you follow up on my suggestions?
As you insist on being rude, I will not reply to any of your questions in the future.
-- Sybrand Bakker, Senior Oracle DBA
Scarab - 29 Dec 2005 07:10 GMT I am so sorry for enraging you. I really feel very sorry for my mistake. I know you have reminded me for more than one times. actually, I am a rookie in newsgroup and I don't know exactly what is the meaning of : top-posting.
Can I bother you to explain it to me? I will never err in it again.
Thank you very much.
> >Because the number of record is very large, so I want to commit every 1000 > >rows, but after commit for the first time, the cursor is not availible any [quoted text clipped - 10 lines] > -- > Sybrand Bakker, Senior Oracle DBA Sybrand Bakker - 29 Dec 2005 09:33 GMT >Can I bother you to explain it to me? I will never err in it again. Rhetorical question: did you learn to read from bottom to top? Do you know the difference between bottom and top at all? Or are you just too lazy to hit a key to get at the end of the previous message? If I recall correctly, the concept of top-posting has been already explained several times to you. Please do not pretend you didn't understand the explanation! Please don't post insincere apologies! It is quite clear you just don't care. As you also ignore every advice that doesn't suit you. As you already know everything better, why do you ask advice here?
-- Sybrand Bakker, Senior Oracle DBA
Scarab - 30 Dec 2005 00:57 GMT > >Can I bother you to explain it to me? I will never err in it again. > [quoted text clipped - 11 lines] > -- > Sybrand Bakker, Senior Oracle DBA I am really very sorry to make such a mistake, and I must apologize for all inconvenience I brought to you, I want to say: it is not insincere. I think I understand what top-posing means till now. Thank you any way.
|
|
|