4

I am trying to figure out how to delete a record using the FOR .. IN .. LOOP

FOR REC IN (SELECT * FROM WORKLIST) LOOP
  GET_DATA(REC);
  --DELETE REC FROM WORKLIST
END LOOP;

The GET_DATA procedure explodes every row to multiple ones so the current one becomes obsolete. I am trying to delete just the current record. Not sure if this is possible using the REC object in this case.

Sadly, WORKLIST does not have any keys.

2 Answers 2

3

Use current of on cursor :

DECLARE
CURSOR c1 IS 
    SELECT * from worklist FOR UPDATE <any column name>; 
BEGIN 
      open c1; 
      loop 
          fetch c1 into crow; 
          exit when c1%notfound;  
          DELETE FROM worklist WHERE CURRENT OF c1; 
      end loop;        
      COMMIT; 
      close c1; 
END;
Sign up to request clarification or add additional context in comments.

9 Comments

For Update is generally discourged. This can cause deadlocks. Read more here asktom.oracle.com/pls/asktom/…
@XING - I think you misunderstood Tom Kyte's response. FOR UPDATE allows us to implement a pessimistic locking strategy which avoids deadlocks.
@APC. In the earlier section it also showed that FOR UPDATE caused deadlocks. I was referring correct. Please refer the whole article
@XING - that's deadlock detected, which causes the second attempted transaction to fail. That's what we want to happen. Without FOR UPDATE both sessions would fail.
@APC. That's what i said. FOR UPDATE can lead to deadlocks. Where did you find me worng here. And thats why he referred an example with Autonomus transaction.
|
2

If WORKLIST has a primary key, just use it:

DELETE FROM WORKLIST WHERE <PK> = REC.<PK>

If no primary key I would try:

DECLARE
  vTmp schema.worklist%rowtype;
BEGIN
  FOR rec IN (SELECT rowid, w.* FROM WORKLIST w) LOOP
    vTmp := null;
    vTmp.col1 := rec.col1;
    vTmp.col2 := rec.col2;
    -- And so on ...
    GET_DATE(vTmp);
    DELETE FROM WORKLIST WHERE rowid = rec.rowid;
  END LOOP;
END;

4 Comments

Sadly, WORKLIST does not have any keys.
Oh I like that, only thing now I get an error on the GET_DATA(REC) line. Error: PLS-00306: wrong number or types of arguments in call to 'GET_DATA'. The definition of that procedure is the following: PROCEDURE GET_DATA(P_REC WWMT_WORKLIST%ROWTYPE) IS ... Is there a way to include ROWID in that ROWTYPE?
I see two options: 1) Declare a cursor with the rowid in a wider scope and use the rowtype of such cursor in both procedures. 2) Use a WORKLIST%ROWTYPE variable and copy all the column values -except rowid- from the current record to the variable. So you will pass the variable to the procedure.
How would I go about doing option 2? I'm not familiar with that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.