Oracle 在更新触发器之前执行时发生约束冲突错误

Oracle 在更新触发器之前执行时发生约束冲突错误,oracle,triggers,Oracle,Triggers,我正在使用oracle提供的示例HR模式试验触发器。 每当使用触发器在DEPARTMENTS表中更新或删除员工各自的部门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 se

我正在使用oracle提供的示例HR模式试验触发器。 每当使用触发器在DEPARTMENTS表中更新或删除员工各自的部门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.

我哪里做错了?完整性约束是否在“触发前”进行检查?

实现您想要的目标是很困难的,但并非不可能

这里的规则是,在将键设置为null之前,必须处理任何可能的约束

我相信,如果我们想要实现一个解决方案,我们需要在这里使用一点动态SQL

这是我快速调整的触发器的修改版本(注意:我还没有测试它):

让我解释一下删除的工作原理:

  • 首先,它获取引用表'EMPLOYEES'的所有外键
  • 然后,对于找到的每个外键,它将获取它引用的表名和列
  • 然后,对于每个表列对,它将使那些与:OLD.DEPARTMENT\u ID匹配的字段的值为空
  • 最后,在处理完所有外键后,它会按照最初的计划将EMPLOYEES表中的DEPARTMENT_ID置空
由于我还没有真正测试过,请告诉我这是否会导致任何问题。

更新主键是非常困难的。如果你一定要这么做,我建议不要使用触发器。在触发器中包含业务规则往往会导致难以维护应用程序,因为代码是隐藏的/零碎的,这使标准DML看起来像魔术(意外的副作用)


尽管如此,在您的情况下,您的错误似乎来自另一个表(可能是
JOB\u HISTORY
?)的外键,并且您的代码逻辑在大多数情况下都应该工作,前提是您更新了所有引用表中的所有子记录。

如果您想使用触发器,则可以删除约束

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.

更新主键是一个非常糟糕的主意,不应该这样做。当您试图更新在其他表中引用的键(外键约束)时,错误很明显。@AbhijithNagarajan删除如何?@Neal如果您只是想传播删除,请在外键的definition@Neal如果你想显示你以前的数据呢?编辑关键信息会丢失参考资料。您将无法再显示以前的数据,除非您将其存储在其他表格中,如历史表格或类似的表格中。例如,您想知道您的员工过去属于哪些部门。但这只是我的一个想法,也许在你的情况下不需要它幸运的是这不会起作用!你真的不想盲目地更新孩子的记录。此外,动态SQL的工作原理并非如此。
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.