web-dev-qa-db-fra.com

Pourquoi je ne reçois pas une erreur de table de mutation dans la gâchette?

Il est (ou au moins) connu que vous ne pouvez pas utiliser des instructions DML sur une table de mutation dans un déclencheur. Un extrait de la Oracle Documentation :

Une table de mutation est une table modifiée par une mise à jour, une suppression ou une instruction insertion, ou une table pouvant être mise à jour par les effets d'une contrainte de cascade Suppr.

La session qui a émis la déclaration de déclenchement ne peut ni interroger ni modifier une table de mutation. Cette restriction empêche une gâchette de voir un ensemble de données incohérentes.

Cependant, je ne peux pas comprendre pourquoi ce déclencheur de démonstration n'échoue pas une erreur "Table de mutation" lorsque j'effectue un insert into emp Utiliser SQL Developer ou 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;

L'insertion se termine avec succès avec la valeur suivante id valeur et met à jour tous les enregistrements emp. J'utilise la base de données Oracle 11G Enterprise Edition version 11.2.0.1.0. J'ai lu sur les déclencheurs composés, mais l'échantillon ne les utilise pas.

11
Centurion

Il y a une exception. Quand vous définissez un before insert, déclencheur au niveau des lignes sur une table et émettre une seule ligne INSERT déclaration, le table is mutating une erreur ne sera pas soulevée. Mais si vous définissez le même type de déclencheur et émettez une instruction à plusieurs lignes INSERT, l'erreur sera soulevée. Voici un exemple:

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

Voici une instruction à une seule ligne insert, qui ne soulever aucune erreur de table de mutation:

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

Voici une instruction insertion à plusieurs lignes, qui augmentera l'erreur de la table de mutation:

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'
12
Nicholas Krasnov