Oracle

為什麼我在觸發器中沒有收到變異表錯誤?

  • December 23, 2013

(或至少是)已知您不能在觸發器內的變異表上使用 DML 語句。Oracle 文件的摘錄:

變異表是正在被 UPDATE、DELETE 或 INSERT 語句修改的表,或者是可能會因 DELETE CASCADE 約束的影響而更新的表。

發出觸發語句的會話不能查詢或修改變異表。此限制可防止觸發器看到不一致的數據集。

insert into emp但是,當我執行使用 SQL Developer 或 SQL*Plus時,我無法理解為什麼這個展示觸發器沒有因“mutating table”錯誤而失敗:

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;

插入使用下一個id值成功完成並更新所有emp記錄。我正在使用 Oracle Database 11g 企業版 11.2.0.1.0 版。我已閱讀有關複合觸發器的資訊,但範例未使用它們。

有一個例外。當您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

這是一個單行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

這是一個多行插入語句,它會引髮變異表錯誤:

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'

引用自:https://dba.stackexchange.com/questions/29244