Vous avez quelques problèmes ici, notamment :
IN_DATE
est déclarée comme une date, vous n'avez donc pas besoin de la passer parTO_DATE()
.- Vous n'avez besoin que d'une seule boucle de curseur ; si vous souhaitez traiter toutes les mises à jour pour un
employee_id
ensemble pour une raison quelconque, vous pouvez ajouter unorder by
clause. - Vous n'avez pas du tout besoin de SQL dynamique ; vous pouvez utiliser les valeurs du curseur dans le cadre d'une mise à jour SQL statique.
Ainsi, une version simple avec une seule boucle pourrait ressembler à :
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;
Ceci utilise le for update
et where current of
des constructions à la fois pour verrouiller la ligne avec laquelle vous travaillez et pour simplifier la mise à jour ; voir la documentation ici
.
Il convient de noter que si soit effective_date
ou p_date
a une composante temporelle qu'ils ne correspondent pas. C'est peu probable pour p_date
, mais plus difficile à deviner pour effective_date
. Si c'est le cas, vous devez soit trunc()
ou utilisez between
pour rechercher une plage de temps.