oracle - Issue with Bulk Collect -
i have procedure need fetch data cursor using bulk collect. issue approach - records getting processed , arent. unable identify root cause. when try debug issue, toad unresponsive , times out. here code. please help!
procedure getpendingitems(pprogramidlst in varchar2, eventcur out cur) vsessionid number; vdefaultvalue svoltp.param.defaultvalue%type; type eventrec table of trigeventqueue.trigeventqueueid%type; type eventpartitiondate table of trigeventqueue.partitiondate%type; veventrec eventrec; veventpartitiondate eventpartitiondate; voldestpossibledate date; vtrigeventqueueid varchar2 (250); vprogramidlst varchar2 (250); vetinterval number; vcount number; vcount1 number; cursor prcursor(vcount1 number) select trigeventqueueid, partitiondate trigeventqueue trigeventqueueid in (select trigeventqueueid ( select teq.trigeventqueueid, teq.partitiondate, teq.eventprocessingsessionid,teq.trigeventstateid svoltp.trigeventqueue teq, programtrigevent pte, trigevent te teq.trigeventstateid = gceventstatepending , teq.eventprocessingsessionid null , teq.programtrigeventid = pte.programtrigeventid , pte.trigeventid = te.trigeventid , teq.partitiondate > (sysdate - (te.numhoursuntileventexpired / 24)) , teq.partitiondate > voldestpossibledate order teq.trigeventcreatedts) rownum <= vcount1) update of a.trigeventqueueid, a.partitiondate skip locked; begin vsessionid := trigeventsessionidseq.nextval; vprogramidlst := pprogramidlst; select defaultvalue vdefaultvalue svoltp.param paramid = gcmaxpeneventsparam; select defaultvalue vetinterval svoltp.param paramid = 2755; -- use max number of expiry hours identify oldest possible date/time event picked for. select sysdate - (max (numhoursuntileventexpired) / 24) voldestpossibledate trigevent; select count(1) vcount1 ( select teq.trigeventqueueid, teq.partitiondate svoltp.trigeventqueue teq, programtrigevent pte, trigevent te teq.trigeventstateid = gceventstatepending , teq.eventprocessingsessionid null , teq.programtrigeventid = pte.programtrigeventid , pte.trigeventid = te.trigeventid , teq.partitiondate > (sysdate - (te.numhoursuntileventexpired / 24)) , teq.partitiondate > voldestpossibledate order teq.trigeventcreatedts) rownum <= vdefaultvalue; if vcount1 > 0 select count(1) vcount etinstancestatus datediff ('ss', instanceupdatetime, sysdate) < vetinterval; if vcount > 0 vcount1 := round(vcount1/vcount); else vcount1 := vcount1; end if; end if; open prcursor(vcount1); loop fetch prcursor bulk collect veventrec, veventpartitiondate limit 100; -- exit when prcursor%notfound; --svoltp.pkgsvoltplock.sleep(1); forall in veventrec.first .. veventrec.last update svoltp.trigeventqueue teq set teq.eventprocessingsessionid = vsessionid, teq.trigeventstateid = gceventstatelocked, --6 : locked state teq.lastuser = 1003, teq.lastupdate = sysdate teq.trigeventqueueid = veventrec (i) , teq.partitiondate = veventpartitiondate (i); end loop; commit; close prcursor; open eventcur select trigeventqueueid, programtrigeventid, partitiondate svoltp.trigeventqueue teq teq.eventprocessingsessionid = vsessionid , teq.trigeventstateid = gceventstatelocked , teq.partitiondate > voldestpossibledate; exception when others open eventcur select 1 dual 1 = 2; end getpendingitems;
it looks you've commented out exit
part of attempt @ debugging - , causing toad unresponsive, means loop never exits (as tony andrews pointed out).
with exit
had it, won't process if cursor query finds fewer 100 rows, you'll see prcursor%notfound
though data retrieved. , if finds more 100 rows you'll process first batch, still lose records last batch of less 100.
so need move exit
end of loop , change condition:
loop fetch prcursor bulk collect veventrec, veventpartitiondate limit 100; --svoltp.pkgsvoltplock.sleep(1); forall in 1 .. veventrec.count update svoltp.trigeventqueue teq set teq.eventprocessingsessionid = vsessionid, teq.trigeventstateid = gceventstatelocked, --6 : locked state teq.lastuser = 1003, teq.lastupdate = sysdate teq.trigeventqueueid = veventrec (i) , teq.partitiondate = veventpartitiondate (i); exit when veventrec.count < 100; end loop;
i've changed forall
loop use 1..count
rather first..last
won't have problem if last actual batch 100 rows, , next 1 gets 0 rows - it'll nothing in forall
, exit.
this scenario covered in second half of this oracle magazine article ('kicking %notfound habit').
Comments
Post a Comment