Você tem alguns problemas aqui, incluindo:
IN_DATE
é declarado como uma data, então você não precisa passar porTO_DATE()
.- Você só precisa de um loop de cursor; se você quiser processar todas as atualizações de um
employee_id
juntos, por algum motivo, você pode adicionar umorder by
cláusula. - Você não precisa de SQL dinâmico; você pode usar os valores do cursor como parte de uma atualização SQL estática.
Portanto, uma versão simples com um único loop pode ser algo como:
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;
Isso está usando o
for update
e where current of
construções para bloquear a linha com a qual você está trabalhando e para simplificar a atualização; consulte a documentação aqui
. Vale a pena notar que, se
effective_date
ou p_date
tem um componente de tempo que não corresponderá. É improvável para p_date
, mas mais difícil de adivinhar para effective_date
. Se isso acontecer, você precisará trunc()
ou use between
para procurar um intervalo de vezes.