2017-02-15 22 views
1

Я пытаюсь обновить зарплату сотрудников, использующих forall. Всякий раз, когда во время обновления возникает какая-либо ошибка, мне нужно сохранить, для которой произошла ошибка идентификатора сотрудника. Но это дает следующее сообщение об ошибке при компиляции Error (14,24): PLS-00201: идентификатор 'INDX' должен быть объявленПолучение неудачных идентификаторов для всех исключений за исключением

Ниже мой код

PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE) 
IS 
    lv_error_string VARCHAR2(4000); 
BEGIN 
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS 
    EXECUTE IMMEDIATE 'UPDATE EMPLOYEES SET SALARY=SALARY+10000 WHERE EMP_ID=:1' 
    USING V_EMP_ID(INDX); 
EXCEPTION 
    WHEN OTHERS 
    THEN 
    FOR J IN 1 .. SQL%BULK_EXCEPTIONS.COUNT 
    LOOP 
     lv_error_string:=lv_error_string 
        ||sqlerrm (-sql%bulk_exceptions(j).error_code) 
        || ' for'||V_EMP_ID(INDX); 
    END LOOP; 
END; 

ответ

2

Используйте это: Ошибка в том, что в exception block вы пытаетесь получить доступ к переменной цикла, которая используется в begin block.

Так что ваши || ' for'||V_EMP_ID(INDX); должны быть || ' for'||V_EMP_ID(J);

CREATE OR REPLACE PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE) 
IS 
    lv_error_string VARCHAR2(4000); 
BEGIN 
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS 
    EXECUTE IMMEDIATE 'UPDATE EMPLOYEES SET SALARY=SALARY+10000 WHERE EMP_ID=:1' 
    USING V_EMP_ID(INDX); 
EXCEPTION 
    WHEN OTHERS 
    THEN 
    FOR J IN 1 .. SQL%BULK_EXCEPTIONS.COUNT 
    LOOP 
     lv_error_string:=lv_error_string 
        ||sqlerrm (-sql%bulk_exceptions(j).error_code) 
        || ' for'||V_EMP_ID(J); 
    END LOOP; 
END; 

Не уверен, почему вы используете Execute Immediate, когда вы можете легко сделать, как показано ниже:

CREATE OR REPLACE PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE) 
IS 
    lv_error_string VARCHAR2(4000); 
BEGIN 
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS 
    UPDATE EMPLOYEES 
    SET SALARY=SALARY+10000 
    WHERE EMP_ID= V_EMP_ID(INDX); 

EXCEPTION 
    WHEN OTHERS 
    THEN 
    FOR J IN 1 .. SQL%BULK_EXCEPTIONS.COUNT 
    LOOP 
     lv_error_string:=lv_error_string 
        ||sqlerrm (-sql%bulk_exceptions(j).error_code) 
        || ' for'||V_EMP_ID(J); 
    END LOOP; 
END; 
+0

Это работает, но не дает мне идентификатор сотрудника, для которого произошла ошибка @ XING – PTK

+0

Так подходит к вашему вопросу я не знаю, почему вы делаете 'выполнить немедленное 'когда вы можете напрямую запустить' update'. См. Мое обновленное сообщение. Вы не получаете никакого 'employee_id' coz oracle doenot, чтобы найти какое-либо« исключение ». – XING

0

Я хотел бы предложить, чтобы пойти с одним оператором DML. И да Loggins ошибка DML является possible.Hope это помогает

--Creating a error log table 
BEGIN 
    DBMS_ERRLOG.create_error_log (dml_table_name => 'EMPLOYEES'); 
END; 
/
--ERR$_EMPLOYEES --> Errro table created 


--Insertion with erroreous record 
UPDATE EMPLOYEES 
SET SALARY   = SALARY + 10000 
where EMP_ID    in (<EMP_ID COLLECTION array 
OR simple EMP_IDs>) LOG ERRORS 
INTO ERR$_EMPLOYEES ('UPDATE') REJECT LIMIT UNLIMITED; 

--Error will be logged into ERR$_EMPLOYEES table 
+1

LOG ERRORS - отличная идея, но помните, что он сохранит строки, успешно измененные в одном выражении, который сильно отличается от SAVE EXCEPTIONS (подавление ошибок на уровне инструкций). –

+0

Да. Я рассмотрел только обработку ошибок на уровне строк здесь –

 Смежные вопросы

  • Нет связанных вопросов^_^