Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Pemicu Oracle setelah memasukkan atau menghapus

Apa yang Anda temui adalah pengecualian klasik "tabel bermutasi". Dalam pemicu ROW, Oracle tidak mengizinkan Anda menjalankan kueri terhadap tabel tempat pemicu didefinisikan - jadi ini adalah SELECT terhadap TABEL1 di DELETING bagian dari pemicu yang menyebabkan masalah ini.

Ada beberapa cara untuk mengatasi hal ini. Mungkin yang terbaik dalam situasi ini adalah menggunakan pemicu majemuk, yang akan terlihat seperti:

CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG
  FOR INSERT OR DELETE ON TABLE1
COMPOUND TRIGGER
  TYPE NUMBER_TABLE IS TABLE OF NUMBER;
  tblTABLE2_IDS  NUMBER_TABLE;

  BEFORE STATEMENT IS
  BEGIN
    tblTABLE2_IDS := NUMBER_TABLE();
  END BEFORE STATEMENT;

  AFTER EACH ROW IS
  BEGIN
    IF INSERTING THEN
      UPDATE TABLE2 t2
        SET    t2.TABLE2NUM = :new.NUM
        WHERE  t2.ID = :new.TABLE2_ID;
    ELSIF DELETING THEN
      tblTABLE2_IDS.EXTEND;
      tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.TABLE2_ID;
    END IF;
  END AFTER EACH ROW;

  AFTER STATEMENT IS
  BEGIN
    IF tblTABLE2_IDS.COUNT > 0 THEN
      FOR i IN tblTABLE2_IDS.FIRST..tblTABLE2_IDS.LAST LOOP
        UPDATE TABLE2 t2
          SET t2.TABLE2NUM = (SELECT NUM
                                FROM (SELECT t1.NUM
                                        FROM TABLE1 t1
                                        WHERE t1.TABLE2_ID = tblTABLE2_IDS(i) 
                                        ORDER BY modification_date DESC)
                                WHERE ROWNUM = 1)
          WHERE t2.ID = tblTABLE2_IDS(i);
      END LOOP;
    END IF;
  END AFTER STATEMENT;
END TABLE1_NUM_TRG;

Pemicu gabungan memungkinkan setiap titik waktu (BEFORE STATEMENT , BEFORE ROW , AFTER ROW , dan AFTER STATEMENT ) untuk ditangani. Perhatikan bahwa titik waktu selalu dipanggil dalam urutan yang diberikan. Ketika pernyataan SQL yang sesuai (yaitu INSERT INTO TABLE1 atau DELETE FROM TABLE1 ) dieksekusi dan pemicu ini dipicu, titik waktu pertama yang dipanggil adalah BEFORE STATEMENT , dan kode di BEFORE STATEMENT handler akan mengalokasikan tabel PL/SQL untuk menampung banyak angka. Dalam hal ini angka yang akan disimpan dalam tabel PL/SQL akan menjadi nilai TABLE2_ID dari TABLE1. (Tabel PL/SQL digunakan sebagai pengganti, misalnya, array karena tabel dapat menampung sejumlah nilai yang bervariasi, sedangkan jika kita menggunakan array, kita harus mengetahui terlebih dahulu berapa banyak angka yang perlu kita simpan. Kami tidak dapat mengetahui sebelumnya berapa banyak baris yang akan terpengaruh oleh pernyataan tertentu, jadi kami menggunakan tabel PL/SQL).

Ketika AFTER EACH ROW titik waktu tercapai dan kami menemukan bahwa pernyataan yang sedang diproses adalah INSERT, pemicunya terus maju dan melakukan UPDATE yang diperlukan ke TABLE2 karena ini tidak akan menyebabkan masalah. Namun, jika DELETE sedang dilakukan, pemicu menyimpan TABLE1.TABLE2_ID ke dalam tabel PL/SQL yang dialokasikan sebelumnya. Ketika AFTER STATEMENT titik waktu akhirnya tercapai, tabel PL/SQL yang dialokasikan sebelumnya diulang, dan untuk setiap TABLE2_ID yang ditemukan, pembaruan yang sesuai dilakukan.

Dokumentasi di sini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penggunaan FLASHBACK di Oracle

  2. cara mengirim email dengan Pl/sql

  3. Bagaimana saya bisa mengekspor konten tabel Oracle ke file?

  4. Ubah port Oracle dari port 8080

  5. Berapa batas ukuran untuk argumen subprogram varchar2 PL/SQL di Oracle?