多次更新一条记录

Updating one record multiple times

我在多次更新一条记录时遇到错误。

SQL代码:

UPDATE EMPLOYEES 
SET FIRST_NAME='J', 
    LAST_NAME='E', 
    EMAIL='asdfghjvbn789@yahoo.com',
    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='asdfghjvbn789@yahoo.com', 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;

错误消息告诉您更新失败的确切原因:

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

假设您的命名约定是值得信赖的,看来您在 (EMP_ID, START_DATE) 的 JOB_HISTORY 上有一个主键。请注意,触发器将 EMPLOYEE.HIRE_DATE 作为 START_DATE 传递,这意味着它对于 JOB_HISTORY 中的所有记录都是相同的。

因此,对于 table 中的每个员工,您只能有一个记录。这对于日记 table 来说似乎过于严格,可能不是您想要的。

所以正确的解决方案是用 START_DATE 值填充 JOB_HISTORY 的方法,这些值代表每个分配的开始,因此每个记录都会不同。

或者,您需要向该键添加另一列。您可以使用 END_DATE,因为它表示旧分配的结束。或者一个新列,例如序列 ID 或时间戳,您可以使用它们来跟踪员工的历史记录。


您在评论中说您根本无法更改数据结构。这样就可以正确设置赋值 START_DATE。鉴于工作历史代表已结束任务的日志,您可以通过以下方式找到当前(即将结束)任务的开始日期:

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

此逻辑的适当位置应在 add_job_history() 中,并忽略或删除 p_start_date 参数。您可以将它放在触发代码中,但那样比较笨拙。