Hai alcuni problemi qui, tra cui:
IN_DATE
è dichiarato come data, quindi non è necessario passarlo tramiteTO_DATE()
.- Hai bisogno solo di un ciclo del cursore; se desideri elaborare tutti gli aggiornamenti per un
employee_id
insieme per qualche motivo puoi aggiungere unorder by
clausola. - Non hai affatto bisogno di SQL dinamico; puoi utilizzare i valori del cursore come parte di un aggiornamento SQL statico.
Quindi una versione semplice con un singolo ciclo potrebbe assomigliare a:
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;
Questo sta usando il for update
e where current of
costrutti per bloccare la riga con cui stai lavorando e per semplificare l'aggiornamento; vedere la documentazione qui
.
Vale la pena notare che se o effective_date
o p_date
ha una componente temporale che non corrisponderanno. È improbabile per p_date
, ma più difficile da indovinare per effective_date
. In tal caso, devi trunc()
o usa between
per cercare un intervallo di volte.