Je hebt hier een paar problemen, waaronder:
IN_DATE
is gedeclareerd als een datum, dus u hoeft deze niet door te geven viaTO_DATE()
.- Je hebt maar één cursorlus nodig; als u alle updates voor een
employee_id
. wilt verwerken samen kun je om de een of andere reden eenorder by
clausule. - Je hebt helemaal geen dynamische SQL nodig; je kunt de waarden van de cursor gebruiken als onderdeel van een statische SQL-update.
Dus een eenvoudige versie met een enkele lus kan er ongeveer zo uitzien:
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;
Dit gebruikt de for update
en where current of
constructies om zowel de rij waarmee u werkt te vergrendelen als de update te vereenvoudigen; zie de documentatie hier
.
Het is vermeldenswaard dat als ofwel effective_date
of p_date
heeft een tijdcomponent die ze niet zullen matchen. Het is onwaarschijnlijk voor p_date
, maar moeilijker te raden voor effective_date
. Als dit het geval is, moet u ofwel trunc()
het, of gebruik between
om meerdere keren te zoeken.