Cen*_*ion 11 trigger oracle oracle-11g
众所周知(或至少是)您不能在触发器内的变异表上使用 DML 语句。Oracle 文档的摘录:
变异表是由 UPDATE、DELETE 或 INSERT 语句修改的表,或者可能受 DELETE CASCADE 约束影响更新的表。
发出触发语句的会话不能查询或修改变异表。此限制可防止触发器看到一组不一致的数据。
但是,当我执行insert into empusing SQL Developer 或 SQL*Plus时,我不明白为什么这个演示触发器不会因“变异表”错误而失败:
CREATE OR REPLACE TRIGGER emp_bri
BEFORE INSERT ON emp
FOR EACH ROW
BEGIN
SELECT max(id) + 1 INTO :NEW.id FROM emp;
UPDATE emp SET salary = 5000;
END emp_bri;
Run Code Online (Sandbox Code Playgroud)
插入成功完成下一个id值并更新所有emp记录。我使用的是 Oracle 数据库 11g 企业版 11.2.0.1.0 版。我已阅读有关复合触发器的信息,但示例并未使用它们。
Nic*_*nov 12
有一个例外。在before insert表上定义行级触发器并发出单行INSERT语句时,table is mutating不会引发错误。但是如果定义同一种触发器并发出多行INSERT语句,则会引发错误。下面是一个例子:
SQL> create table TB_TR_TEST(
2 col1 number,
3 col2 number
4 )
5 ;
Table created
SQL> create or replace trigger TR_TB_TR_TEST
2 before insert on TB_TR_TEST
3 for each row
4 begin
5 SELECT max(col1) + 1 INTO :NEW.col1
6 FROM TB_TR_TEST;
7 UPDATE TB_TR_TEST SET col2 = 5000;
8 end;
9 /
Trigger created
Run Code Online (Sandbox Code Playgroud)
这是一个单行insert语句,它不会引发变异表错误:
SQL> insert into TB_TR_TEST(col1, col2) values(1,2);
1 row inserted
SQL> insert into TB_TR_TEST(col1, col2) values(3,5);
1 row inserted
SQL> commit;
Commit complete
Run Code Online (Sandbox Code Playgroud)
这是一个多行插入语句,它会引发变异表错误:
SQL> insert into TB_TR_TEST(col1, col2)
2 select 1, 2
3 from dual;
insert into TB_TR_TEST(col1, col2)
select 1, 2
from dual
ORA-04091: table HR.TB_TR_TEST is mutating, trigger/function may not see it
ORA-06512: at "HR.TR_TB_TR_TEST", line 2
ORA-04088: error during execution of trigger 'HR.TR_TB_TR_TEST'
Run Code Online (Sandbox Code Playgroud)