我正在使用oracle提供的示例HR模式试验触发器。 我试图在使用触发器在DEPARTMENTS TABLE中更新或删除各自的部门ID时删除或更新所有员工。
这是代码:
create or replace trigger UPDATE_EMPLOYEES_DEPT_ID
before update or delete of DEPARTMENT_ID on DEPARTMENTS
for each row
begin
if UPDATING then
update EMPLOYEES set DEPARTMENT_ID = :new.DEPARTMENT_ID where DEPARTMENT_ID = :OLD.DEPARTMENT_ID;
ELSIF DELETING then
update employees set department_id = null where DEPARTMENT_ID = :OLD.DEPARTMENT_ID;
end if;
end;
当我执行时:
UPDATE departments SET department_ID = 112 WHERE department_ID = 110;
它给了我约束违规错误。
Error report:
SQL Error: ORA-02292: integrity constraint (HR.JHIST_DEPT_FK) violated - child record found
02292. 00000 - "integrity constraint (%s.%s) violated - child record found"
*Cause: attempted to delete a parent key value that had a foreign
dependency.
*Action: delete dependencies first then parent or disable constraint.
我哪里错了?是否在'BEFORE TRIGGER'之前检查了完整性约束?
答案 0 :(得分:1)
更新主键是probably not a good idea.。如果你绝对必须这样做,我建议不要使用触发器。在触发器中使用业务规则往往会导致难以维护的应用程序,因为代码是隐藏/分段的,它使标准DML看起来像魔术(意外的副作用)。
尽管如此,在您的情况下,您的错误似乎来自另一个表中的外键(可能是JOB_HISTORY
?),并且您的代码逻辑应该在大多数情况下都有效,前提是您更新了所有子记录所有引用表。
答案 1 :(得分:0)
实现你想要的东西是非常有问题的,但并非不可能。
这里的交易是你必须在将密钥设置为null之前处理任何可能的约束。
如果我们想要实现解决方案,我相信我们需要在这里使用一点动态SQL。
这是我快速调整的触发器的修改版本(注意:我还没有测试过):
create or replace trigger UPDATE_EMPLOYEES_DEPT_ID
before update or delete of DEPARTMENT_ID on DEPARTMENTS
for each row
begin
if UPDATING then
update EMPLOYEES set DEPARTMENT_ID = :new.DEPARTMENT_ID where DEPARTMENT_ID = :OLD.DEPARTMENT_ID;
elsif DELETING then
for i in ( select CONSTRAINT_NAME from USER_CONSTRAINTS where CONSTRAINT_TYPE='R' and R_CONSTRAINT_NAME in (select CONSTRAINT_NAME from USER_CONSTRAINTS where CONSTRAINT_TYPE in ('P','U') and TABLE_NAME='EMPLOYEES') )
loop
for j in ( select TABLE_NAME, COLUMN_NAME from USER_CONS_COLUMNS where CONSTRAINT_NAME = i.CONSTRAINT_NAME )
loop
update j.TABLE_NAME set j.COLUMN_NAME = null where j.COLUMN_NAME = :OLD.DEPARTMENT_ID;
end loop;
end loop;
update EMPLOYEES set DEPARTMENT_ID = null where DEPARTMENT_ID = :OLD.DEPARTMENT_ID;
end if;
end;
让我解释一下有关删除的一些方法:
由于我没有真正测试过这个,请告诉我这是否会导致任何问题。
答案 2 :(得分:0)
如果您想使用触发器,则可以删除约束
I mean, perform all the operation of update delete by trigger only. and remove the constraint.
but doing so is not a good practice. So be sure with whatever you want to do.