Tetikleyicide neden bir mutasyon tablosu hatası almıyorum?


11

Bir tetikleyicinin içindeki bir mutasyon tablosunda DML ifadelerini kullanamayacağınız (veya en azından) biliniyordu. Oracle belgelerinden bir alıntı :

Bir mutasyon tablosu, UPDATE, DELETE veya INSERT deyimi tarafından değiştirilen bir tablo veya DELETE CASCADE sınırlamasının etkileriyle güncellenebilecek bir tablodur.

Triggering deyimini veren oturum, bir mutasyon tabloyu sorgulayamaz veya değiştiremez. Bu kısıtlama, bir tetikleyicinin tutarsız bir veri kümesi görmesini engeller.

Ancak, bir insert into empSQL Developer veya SQL * Plus kullanarak gerçekleştirirken bu demo tetikleyicisinin neden "mutasyon tablosu" hatasıyla başarısız olmadığını anlayamıyorum :

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;

Ekleme, bir sonraki iddeğerle başarıyla tamamlanır ve tüm empkayıtları günceller . Oracle Database 11g Enterprise Edition Sürüm 11.2.0.1.0'ı kullanıyorum. Bileşik tetikleyiciler hakkında okudum ancak örnek bunları kullanmıyor.


1
Sorunuzun İlgisiz ama: do DEĞİL kullanmak select max(id)eşsiz numaraları atamak için. Sadece yapma. Bu sadece yanlıştır ve ölçeklenmez.
a_horse_with_no_name

Evet, biliyorum :) Örnek bu durumda muhtemelen çok iyi değil ... Otomatik entrimleme değerleri kesinlikle diziler ve tetikleyiciler kullanılarak uygulanmalıdır.
Centurion

Bu kesinlikle garip. Btw: İşte SQLFiddle örneği sqlfiddle.com/#!4/9e59f/2
a_horse_with_no_name

Bilgi paylaştığınız için teşekkürler, havalı bağlantı. Böyle Oracle SQL test web sitesi olduğunu bilmiyordum :)
Centurion

a_horse_with_no_name: Başka bir örnek: Fiddle-test-2 (SET maaş = maaş + 10)
ypercubeᵀᴹ

Yanıtlar:


12

Bir istisna var. before insertTabloda satır düzeyinde bir tetikleyici tanımlayıp tek satırlık bir INSERTifade verdiğinizde table is mutatinghata ortaya çıkmaz. Ancak aynı tür bir tetikleyici tanımlar ve çok satırlı bir INSERTifade verirseniz , hata ortaya çıkar. İşte bir örnek:

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

İşte tek sıralı olan insertmutasyona tablo hatası yükseltmez açıklamada,:

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

Mutasyon tablosu hatasını artıracak çok satırlı bir ekleme ifadesi:

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'

Bu suçlu gibi görünüyor. Bu davranış için kılavuzda bir referansınız var mı?
a_horse_with_no_name

support.oracle.com'a erişiminiz varsa @a_horse_with_no_name, ID 132569.1( ORA-4091 on BEFORE ROW TRIGGER with INSERT .. into SELECT statement) öğesini arayın .
Nicholas Krasnov

2
Teşekkürler. İlginçtir ki bu istisna sadece 8i (!) Kılavuzlarında belgelenmiştir : docs.oracle.com/cd/F49540_01/DOC/server.815/a68003/… (" " Mutasyon ve Kısıtlama Tabloları " bölümü ) t Bu ifadeyi güncel kılavuzlarda
bulamayız
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.