जैसा कि आपके पिछले प्रश्न पर एक टिप्पणी में उल्लेख किया गया है , आपका दूसरा कर्सर पहले कर्सर द्वारा पाए गए कर्मचारी तक सीमित नहीं है क्योंकि आपके पास उनके बीच कोई लिंक नहीं है। आपके पास कहां है:
and employee_id = employee_id
... वे दोनों तालिका कॉलम को संदर्भित करते हैं, इसलिए यह फ़िल्टर के रूप में बिल्कुल भी कार्य नहीं करता है। आपने अपने स्थानीय चर को वही नाम दिया है, जो चीजों को काफी भ्रमित करता है, लेकिन यह वैसे भी दायरे से बाहर है - इस कर्सर में प्रक्रिया के मुख्य भाग में निर्धारित चर मान की कोई दृश्यता नहीं है।
आपको कुछ ऐसा करने की ज़रूरत है:
CREATE OR REPLACE PROCEDURE sp_run_employee_updates (p_date IN DATE) IS
update_sql varchar2(4000);
first_update boolean;
CURSOR c_employees IS
SELECT DISTINCT employee_id
FROM bi_employee_update
WHERE effective_date = p_date
AND executed = 'N'
AND activity_id = '0';
CURSOR c_updates(cp_employee_id bi_employee_update.employee_id%TYPE) IS
SELECT *
FROM bi_employee_update
WHERE effective_date = p_date
AND executed = 'N'
AND activity_id = '0'
AND employee_id = cp_employee_id
FOR UPDATE;
BEGIN
-- loop around all employees with pending records
FOR r_employee IN c_employees LOOP
-- reset the update_sql variable to its base
update_sql := 'UPDATE BI_EMPLOYEE SET ';
-- reset the flag so we only add the comments etc. on the first record
first_update := true;
-- loop around all pending records for this employee
FOR r_update IN c_updates(r_employee.employee_id) LOOP
-- add the comments etc., only for the first update we see
if first_update then
update_sql := update_sql
|| ' comments = ''' || r_update.comments || ''','
|| ' updated_by = ''' || r_update.changed_by || ''','
|| ' updated_on = ''' || r_update.changed_on || ''','
|| ' effective_date = ''' || r_update.effective_date || '''';
first_update := false;
end if;
-- add the field/value from this record to the variable
update_sql := update_sql || ', '
|| r_update.column_name || ' = ''' || r_update.new_value || '''' ;
-- mark this update as executed
UPDATE bi_employee_update
SET executed = 'Y'
WHERE CURRENT OF c_updates;
END LOOP;
-- apply this update to the bi_employee record
update_sql := update_sql || ' WHERE emp_id = ' || r_employee.employee_id;
DBMS_OUTPUT.PUT_LINE(update_sql);
EXECUTE IMMEDIATE update_sql;
END LOOP;
END sp_run_employee_updates;
वास्तव में, महत्वपूर्ण अंतर यह है कि दूसरे कर्सर में अब एक पैरामीटर है, और पहले कर्सर से कर्मचारी आईडी को उस पैरामीटर के रूप में पास किया जाता है।
साथ ही, IN_DATE
एक तिथि के रूप में घोषित किया गया है, इसलिए आपको इसे TO_DATE()
. के माध्यम से पारित करने की आवश्यकता नहीं है . अन्य स्थानों (प्रभावी तिथियां इत्यादि) में निहित तिथि रूपांतरण होने जा रहे हैं क्योंकि आप उन्हें तारों के रूप में मान रहे हैं, लेकिन जब तक उनके पास समय घटक नहीं हैं, यह शायद कुछ भी नहीं तोड़ देगा क्योंकि यह लगातार होना चाहिए प्रक्रिया।