Masz tutaj kilka problemów, w tym:
IN_DATE
jest zadeklarowana jako data, więc nie musisz przekazywać jej przezTO_DATE()
.- Potrzebujesz tylko jednej pętli kursora; jeśli chcesz przetwarzać wszystkie aktualizacje dla
employee_id
razem z jakiegoś powodu możesz dodaćorder by
klauzula. - W ogóle nie potrzebujesz dynamicznego SQL; możesz użyć wartości z kursora jako części statycznej aktualizacji SQL.
Tak więc prosta wersja z pojedynczą pętlą może wyglądać mniej więcej tak:
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;
To używa for update
i where current of
konstruuje zarówno blokowanie wiersza, z którym pracujesz, jak i uproszczenie aktualizacji; zapoznaj się z dokumentacją tutaj
.
Warto zauważyć, że jeśli albo effective_date
lub p_date
zawiera składnik czasowy, z którym nie będą pasować. Jest mało prawdopodobne w przypadku p_date
, ale trudniej odgadnąć dla effective_date
. Jeśli tak, musisz albo trunc()
lub użyj between
szukać różnych czasów.