2

I´m trying to write a CURSOR to make a task in Oracle. I´m not familiarized with cursors in Oracle. Obviously I´m doing something wrong with this. Can someone tell me what it is?.

DECLARE 
    CURSOR c1 IS
        SELECT BADGE.EMPID
        FROM EVENTS
        INNER JOIN BADGE ON EVENTS.CARDNUM = BADGE.ID
        INNER JOIN EMP ON BADGE.EMPID = EMP.ID
        WHERE EMP.VISITOR = 0
        AND EVENTS.EVENT_TIME_UTC - 0.125 > TO_DATE('20090101 00:00:00', 'RRRRMMDD hh24:mi:ss')
        AND EVENTS.EVENT_TIME_UTC - 0.125 < TO_DATE('20120101 23:59:59', 'RRRRMMDD hh24:mi:ss');
    r1 c1%ROWTYPE;
BEGIN
    FOR r1 IN c1 LOOP
    UPDATE EVENTS
    SET EVENTS.EMPID = r1.EMPID
    END LOOP;
END;  

Thanks for your help!

2
  • Is there any error or the events are just not updated? Commented Jun 3, 2013 at 14:35
  • Why are you "obviosuly doing something wrong"? And besides: for this update yo don't need a cursor. You can do that with a single UPDATE statement. For something similar see here: stackoverflow.com/q/16891930/330315 Commented Jun 3, 2013 at 14:36

2 Answers 2

3

There is also a way to do this without a cursor but this is what you want to do. The point is that you define the cursor and then loop along it. Recognize the FOR UPDATE

DECLARE 
  CURSOR c1 IS
    SELECT BADGE.EMPID
    FROM EVENTS
    INNER JOIN BADGE ON EVENTS.CARDNUM = BADGE.ID
    INNER JOIN EMP ON BADGE.EMPID = EMP.ID
    WHERE EMP.VISITOR = 0
    AND EVENTS.EVENT_TIME_UTC - 0.125 > TO_DATE('20090101 00:00:00', 'RRRRMMDD hh24:mi:ss')
    AND EVENTS.EVENT_TIME_UTC - 0.125 < TO_DATE('20120101 23:59:59', 'RRRRMMDD hh24:mi:ss')
    FOR UPDATE of events.empid;
BEGIN
  for l in c1 loop 
    UPDATE events
      SET empid = l.empid
      WHERE CURRENT OF c1;
  end loop;
  COMMIT;
end;
Sign up to request clarification or add additional context in comments.

3 Comments

Be careful, "When SELECT FOR UPDATE queries multiple tables, it locks only rows whose columns appear in the FOR UPDATE clause": docs.oracle.com/cd/E11882_01/appdev.112/e25519/…
Thanks you!, by the way I was missing the ';' inside the loop statement
You are welcome. Now I also see it ... (about the missing semicolon ;)
2

Solution without using implicit cursor (no locking issue):

Begin
  For X in (
        SELECT BADGE.EMPID, EVENTS.CARDNUM FROM EVENTS
        INNER JOIN BADGE ON EVENTS.CARDNUM = BADGE.ID
        INNER JOIN EMP ON BADGE.EMPID = EMP.ID
        WHERE EMP.VISITOR = 0 AND 
              EVENTS.EVENT_TIME_UTC - 0.125 > TO_DATE('20090101 00:00:00', 'RRRRMMDD hh24:mi:ss') AND 
              EVENTS.EVENT_TIME_UTC - 0.125 < TO_DATE('20120101 23:59:59', 'RRRRMMDD hh24:mi:ss')
    )
  Loop
    UPDATE EVENTS
    SET EVENTS.EMPID = X.EMPID
    WHERE EVENTS.CARDNUM = X.CARDNUM;
  END LOOP;
  COMMIT;
END;  

2 Comments

That is syntactic sugar. There is still a cursor, see ""Cursor FOR LOOP statement" docs.oracle.com/cd/E11882_01/appdev.112/e25519/…
And you need a where clause. EMPID is being updated for all rows in the EVENTS table every time.

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.