sql >> Databáze >  >> RDS >> Oracle

Podivné chování s vnořenými kurzory Oracle

Jak je uvedeno v komentáři k vaší předchozí otázce , váš druhý kurzor není omezen na zaměstnance nalezeného prvním kurzorem, protože mezi nimi nemáte žádné spojení. Kde máte:

and employee_id = employee_id

... oba odkazují na sloupec tabulky, takže to vůbec nefunguje jako filtr. Dali jste své lokální proměnné stejný název, což dost mate, ale stejně je to mimo rozsah – tento kurzor nemá žádnou viditelnost hodnoty proměnné nastavené v hlavním těle procedury.

Musíte udělat něco jako:

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;

Důležitý rozdíl je ve skutečnosti v tom, že druhý kurzor má nyní parametr a jako tento parametr se předává ID zaměstnance z prvního kurzoru.

Také IN_DATE je deklarováno jako datum, takže jej nemusíte předávat přes TO_DATE() . Na jiných místech budou implicitní převody dat (účinná data atd.), protože s nimi zacházíte jako s řetězci, ale pokud nemají časové komponenty, pravděpodobně to nic nenaruší, protože by to mělo být konzistentní v rámci postup.




  1. Jak započítám chybějící xPaths a udržím svá data jednotná při seškrabování webu pomocí dotazovací metody DOMXPath?

  2. Chyba PostgreSQL 9.0:sloupec t.tgisconstraint neexistuje

  3. Jak mohu omezit velikost dočasných tabulek?

  4. Jaký je rozdíl mezi AS a IS v uložené proceduře Oracle?