2015-10-13 3 views
0

Я встречаюсь с ошибкой при обновлении одной записи несколько раз.Обновление одной записи несколько раз

SQL код:

UPDATE EMPLOYEES 
SET FIRST_NAME='J', 
    LAST_NAME='E', 
    EMAIL='[email protected]', 
    PHONE_NUMBER='123456789', 
    HIRE_DATE='10/13/2015', 
    JOB_ID=(SELECT JOB_ID FROM JOBS WHERE JOB_TITLE='Programmer'), 
    SALARY=4000, 
    COMMISSION_PCT=0, 
    DEPARTMENT_ID=(SELECT DEPARTMENT_ID FROM DEPARTMENTS WHERE DEPARTMENT_NAME='IT'), 
    MANAGER_ID=(SELECT MANAGER_ID FROM DEPARTMENTS WHERE DEPARTMENT_NAME='IT') 
WHERE EMPLOYEE_ID=15; 

Сообщение об ошибке:

Error starting at line : 1 in command - 
UPDATE EMPLOYEES SET FIRST_NAME='J', LAST_NAME='E', EMAIL='[email protected]', PHONE_NUMBER='123456789', 
HIRE_DATE='10/13/2015', 
JOB_ID=(SELECT JOB_ID FROM JOBS WHERE JOB_TITLE='Programmer'), SALARY=4000, COMMISSION_PCT=0, 
DEPARTMENT_ID=(SELECT DEPARTMENT_ID FROM DEPARTMENTS WHERE DEPARTMENT_NAME='IT'), 
MANAGER_ID=(SELECT MANAGER_ID FROM DEPARTMENTS WHERE DEPARTMENT_NAME='IT') WHERE EMPLOYEE_ID=15 
Error report - 
SQL Error: ORA-00001: unique constraint (GAS.JHIST_EMP_ID_ST_DATE_PK) violated 
ORA-06512: at "GAS.ADD_JOB_HISTORY", line 10 
ORA-06512: at "GAS.UPDATE_JOB_HISTORY", line 2 
ORA-04088: error during execution of trigger 'GAS.UPDATE_JOB_HISTORY' 
00001. 00000 - "unique constraint (%s.%s) violated" 
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key. 
      For Trusted Oracle configured in DBMS MAC mode, you may see 
      this message if a duplicate entry exists at a different level. 
*Action: Either remove the unique restriction or do not insert the key. 

Вот триггер: (опять-таки из раздела комментариев)

CREATE OR REPLACE TRIGGER "GAS"."UPDATE_JOB_HISTORY" 
AFTER UPDATE OF job_id, department_id 
ON employees FOR EACH ROW 

BEGIN 

add_job_history(:old.employee_id, 
       :old.hire_date, 
       sysdate, 
       :old.job_id, 
       :old.department_id); 
END; 
/

ALTER TRIGGER "GAS"."UPDATE_JOB_HISTORY" ENABLE; 

Вот код для add_job_history.

create or replace PROCEDURE add_job_history (p_emp_id job_history.employee_id%type , 
               p_start_date job_history.start_date%type , 
               p_end_date job_history.end_date%type , p_job_id job_history.job_id%type , 
               p_department_id job_history.department_id%type) 
IS 
BEGIN 

INSERT INTO job_history (employee_id, 
         start_date, 
         end_date, 
         job_id, 
         department_id) 
        VALUES(p_emp_id, 
         p_start_date, 
         p_end_date, 
         p_job_id, 
         p_department_id); 
END add_job_history; 
+0

Возможно, вы не можете обновить HIRE_DATE. Это может быть ограничение, возможно, EmployeeId с StartDate является основным ключом здесь. Попробуйте обновить без HIRE_DATE –

+1

Какие-нибудь триггеры? – jarlh

+0

, но в требовании вам также необходимо обновить rent_date –

ответ

0

Сообщение об ошибке говорит вам, почему именно обновление не удается:

SQL Error: ORA-00001: unique constraint (GAS.JHIST_EMP_ID_ST_DATE_PK) violated 

Предполагая, что ваша именовании заслуживает доверия, он появляется у вас есть первичный ключ JOB_HISTORY из (EMP_ID, START_DATE). Обратите внимание, что триггер передает EMPLOYEE.HIRE_DATE как START_DATE, что означает, что он будет одинаковым для всех записей в JOB_HISTORY.

Следовательно, у вас может быть только одна запись для каждого сотрудника в этой таблице. Это кажется слишком ограничительным для журнальной таблицы и, вероятно, не так, как вы планировали.

Таким образом, правильное решение было бы способом получить заполнение JOB_HISTORY значениями START_DATE, которые представляют начало каждого присваивания и, следовательно, будут отличаться для каждой записи.

В качестве альтернативы вам нужно добавить еще один столбец к этому ключу. Вы можете использовать END_DATE, поскольку он сигнализирует о завершении старого назначения. Или новый столбец, такой как идентификатор последовательности или временная метка, который вы можете использовать для отслеживания истории сотрудника.


Вы говорите в комментарии, что вы вообще не можете изменять структуры данных. Это оставляет правильную настройку назначения START_DATE. Учитывая, что история работы представляет собой журнал закрытых заданий, вы можете найти дату начала текущей (около быть закрыты) переуступка:

select max(end_date) 
from job_history 
where employee_id = 15; 

Правильное место для этой логики была бы в add_job_history(), и игнорировать или удалить параметр p_start_date. Вы можете поместить его в код запуска, но это неуклюже.