I have a cursor that queries a table like this
CURSOR Cur IS
SELECT Emp_No,status
from Employee
FOR UPDATE OF status;
Now I would want to update my status in Employee table from another table using the Emp_no. Once I have done this I need to use this status for calling custom business logic and not the original status retrieved by the cursor. What is the best way of going about this? Here is what I have written. I declared a variable called v_status by the way
FOR Rec IN Cur LOOP
BEGIN
UPDATE Employee
SET status = (select a.status from Employee_Status where a.Emp_No = rec.Emp_No)
WHERE CURRENT OF Cur ;
COMMIT;
END;
SELECT status INTO v_status
FROM Employee
where Emp_No = rec.Emp_No;
IF(v_status = 'Active') THEN
-- Custom Business Logic
ELSE
-- Business logic
END IF;
END LOOP;
What would be a better way to achieve this?
1) I’m hoping in your real code that you don’t have a
COMMITin the middle of your loop. Since committing releases the locks held by your transaction, the row-level locks taken out with theFOR UPDATEclause are released and other sessions are free to update the same rows. In later versions of Oracle, you’ll get an “ORA-01002: fetch out of sequence” if you do this. In earlier versions of Oracle, this error was ignored which lead to occasionally incorrect results.2) Do you need to update the
EMPLOYEEtable on a row-by-row basis? I’d tend to move the update outside of the loop in order to maximize SQL since that’s the most efficient way to process data. If your business logic is amenable to it, I’d also suggest doing bulk operations to fetch the data into local collections that your business logic can iterate through in order to minimize context shifts between SQL and PL/SQL.So, based on your comments, in your example, there should be a predicate in the definition of your cursor, right? Something like this?
If so, you’d need that same predicate in the single UPDATE statement (potentially instead of the
EXISTSclause). But since you know that you only want to process the rows that your UPDATE statement affected, you can just return those rows into a local collection