【问题标题】:Trigger before delete删除前触发
【发布时间】:2020-03-12 22:57:37
【问题描述】:

我创建了一个删除前触发器:

create or replace trigger myTrigger3 
before delete on emp
for each row
begin
    update emp set mgr = 'Null' where mgr = :old.emp_name;
end;

桌子在哪里

emp(emp_id integer primary key, emp_name varchar(20), mgr varchar(20))

但是当我运行这个语句时,触发器没有运行。

delete from emp where emp_id = 1004;
select * from emp;

错误报告 -
ORA-04091:表 DB20178004.EMP 正在变异,触发器/函数可能看不到它
ORA-06512:在“DB20178004.MYTRIGGER3”,第 2 行
ORA-04088: 执行触发器 'DB20178004.MYTRIGGER3' 期间出错

【问题讨论】:

  • 当表的数据已经发生变化时,您不能操作表数据。您必须在删除语句后 更新表。一种方法是不带for each row 的删除后触发器,您可以在其中更新所有不再在表中找到的经理。另一种是使用复合触发器,您可以记住 after each row 部分中所有已删除的 ID,并在 after statement 部分中使用它们进行更新。
  • 附注:set mgr = 'Null' 可能应该是set mgr = null。您真的不想将 mgr 设置为包含单词“Null”的字符串,是吗?

标签: oracle plsql ddl database-trigger dml


【解决方案1】:

您可以更喜欢使用set null 选项添加外键约束,而不是这样的触发器。当然你需要一个主键应该已经在emp_id 列上定义了:

alter table emp 
add constraint fk_mgr foreign key(mgr)
references emp(emp_id)
on delete set null;

每当您删除具有与mgr 列匹配值的emp_id 记录时,在删除具有该emp_id 的记录后,这些记录将被清空。

但请选择符合列的mgr 的数据类型(数字) emp_idinteger 可以定义外键 约束。

Demo

顺便说一句,

  • 我建议您使用软删除。例如向表中添加一个活动列和 每当要删除时将其值设置为零,并且不显示 应用程序上 active=0 的记录。
  • 如果您坚持删除,请不要按emp_name 列过滤,因为 可以有多个同名的人,但使用emp_id 就在表中唯一而言更好。

【讨论】:

    猜你喜欢
    • 2010-12-29
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 2021-02-01
    相关资源
    最近更新 更多