多次更新一条记录

时间:2015-10-13 06:29:22

标签: sql oracle indexing unique

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

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;

1 个答案:

答案 0 :(得分:0)

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

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中的所有记录都是相同的。

因此,您只能为该表中的每位员工提供一条记录。对于日记表而言,这似乎过于严格,可能不是您的意图。

因此,正确的解决方案是使用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参数。你可以把它放在触发器代码中,但那是笨重的。