Du har några problem här, inklusive:
IN_DATE
deklareras som ett datum, så du behöver inte passera det genomTO_DATE()
.- Du behöver bara en markörslinga; om du vill bearbeta alla uppdateringar för ett
employee_id
tillsammans av någon anledning kan ni lägga till enorder by
klausul. - Du behöver inte alls dynamisk SQL; du kan använda värdena från markören som en del av en statisk SQL-uppdatering.
Så en enkel version med en enda slinga kan se ut ungefär så här:
CREATE OR REPLACE PROCEDURE sp_run_employee_updates (p_date IN DATE) IS
CURSOR c_updates IS
SELECT *
FROM bi_employee_update
WHERE effective_date = p_date
AND executed = 'N'
AND activity_id = '0'
FOR UPDATE;
BEGIN
-- loop around all pending records
FOR r_update IN c_updates LOOP
-- apply this update to the bi_employee record
UPDATE bi_employee
SET col1 = r_update.col1, col2 = r_update.col2
WHERE emp_id = r_update.employee_id;
-- mark this update as executed
UPDATE bi_employee_update
SET executed = 'Y'
WHERE CURRENT OF c_updates;
END LOOP;
END sp_run_employee_updates;
Detta använder for update
och where current of
konstruktioner för att både låsa raden du arbetar med och för att förenkla uppdateringen; se dokumentationen här
.
Det är värt att notera att om antingen effective_date
eller p_date
har en tidskomponent som de inte matchar. Det är osannolikt för p_date
, men svårare att gissa för effective_date
. Om det gör det måste du antingen trunc()
det, eller använd between
att leta efter ett antal gånger.