【问题标题】:Mutating table trigger error for one type of insert statement一种插入语句的变异表触发器错误
【发布时间】:2019-09-15 21:08:47
【问题描述】:

对于语句 insert into employee select 'xyz',200 from dual,我收到 mutating table error 并且脚本为 insert into employee values ('abc',100); 成功执行。

有人可以解释为什么该语句对于一种类型的插入语句会失败吗?两个脚本都将相似类型的数据插入到表中

脚本详情:

--table creation
create table employee (name varchar2(30),salary number);

--trigger creation
create or replace trigger emp_trig 
before insert on employee
for each row
begin
delete from employee where name=:new.name;
end;
/
--insert statement 1
insert into employee values ('abc',100);
--result : 1 row inserted

--insert statement 2
insert into employee select 'xyz',200 from dual
--result: 

Error report -
ORA-04091: table NMS_CON.EMPLOYEE is mutating, trigger/function may not see it
ORA-06512: at "NMS_CON.EMP_TRIG", line 2
ORA-04088: error during execution of trigger 'NMS_CON.EMP_TRIG'

【问题讨论】:

  • 这纯粹是出于好奇,还是您试图实现的生产代码示例?因为如果是后者,不要使用触发器,而是使用merge语句而不是insert语句!
  • 在生产代码中遇到了一些问题。在对此进行一些研究时,我最终得出了上述疑问。所示示例仅用于说明目的
  • 一般来说,对于定义触发器的每一行触发器,您应该避免触及 a 内的同一个表。
  • 是的,但触发器在第一次查询时工作正常。
  • 触发器是否适用于insert ... values... 语句并不重要,它是否适用于insert ... select ... 语句。避免这种触发“解决方案”,并寻求通过不同的解决方案来实现您的目标。

标签: plsql triggers mutating-table


【解决方案1】:

插入单行不会导致变异表错误 - 怎么可能,因为该行以前不存在?

但是 insert-select 可能涉及不止一行,所以你会得到错误。

通常,您的触发器中不应包含非查询 DML 操作。太多可能的副作用和不良后果。

更好的方法是编写一个为您执行插入操作的过程,不要直接对表授予插入权限,只授予拥有该过程的包。然后在该过程中,您可以在插入之前进行删除,或者您可以进行合并 - 或其他任何操作。

所有逻辑都隐藏在过程中,通过限制表上的权限,您可以确保必须调用过程。

希望有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-17
    • 2015-02-05
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多