Имате няколко проблема тук, включително:
IN_DATE
се декларира като дата, така че не е необходимо да го предавате презTO_DATE()
.- Необходим ви е само един цикъл на курсора; ако искате да обработите всички актуализации за
employee_id
заедно по някаква причина можете да добавитеorder by
клауза. - Изобщо не се нуждаете от динамичен SQL; можете да използвате стойностите от курсора като част от статична актуализация на SQL.
Така че една проста версия с единичен цикъл може да изглежда така:
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;
Това използва for update
и where current of
конструкции както за заключване на реда, с който работите, така и за опростяване на актуализацията; вижте документацията тук
.
Струва си да се отбележи, че ако effective_date
или p_date
има времеви компонент, който няма да съвпадат. Малко вероятно е за p_date
, но по-трудно за отгатване за effective_date
. Ако го направи, трябва или да trunc()
или използвайте between
за да търсите диапазон от времена.