Tiene algunos problemas aquí, que incluyen:
IN_DATE
se declara como una fecha, por lo que no necesita pasarla a través deTO_DATE()
.- Solo necesita un bucle de cursor; si desea procesar todas las actualizaciones para un
employee_id
juntos, por alguna razón, puede agregar unorder by
cláusula. - No necesita SQL dinámico en absoluto; puede usar los valores del cursor como parte de una actualización de SQL estático.
Entonces, una versión simple con un solo ciclo podría verse así:
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;
Esto está usando el for update
y where current of
construcciones para bloquear la fila con la que está trabajando y para simplificar la actualización; consulte la documentación aquí
.
Vale la pena señalar que si effective_date
o p_date
tiene un componente de tiempo que no coincidirá. Es poco probable para p_date
, pero más difícil de adivinar para effective_date
. Si es así, debe trunc()
o usa between
para buscar un intervalo de horas.