Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Wyzwalacz Oracle po wstawieniu lub usunięciu

To, na co natknąłeś się, to klasyczny wyjątek „tabeli mutacji”. W wyzwalaczu ROW Oracle nie pozwala na uruchomienie zapytania względem tabeli, w której zdefiniowano wyzwalacz — więc jest to SELECT względem TABLE1 w DELETING część wyzwalacza, który powoduje ten problem.

Jest kilka sposobów na obejście tego. Być może najlepszym rozwiązaniem w tej sytuacji jest użycie wyzwalacza złożonego, który wygląda następująco:

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;

Wyzwalacz złożony zezwala na każdy punkt czasowy (BEFORE STATEMENT , BEFORE ROW , AFTER ROW i AFTER STATEMENT ) do rozpatrzenia. Zauważ, że punkty czasowe są zawsze wywoływane w podanej kolejności. Kiedy odpowiednia instrukcja SQL (np. INSERT INTO TABLE1 lub DELETE FROM TABLE1 ) jest wykonywany i wyzwalacz jest uruchamiany, a pierwszym punktem czasowym do wywołania będzie BEFORE STATEMENT i kod w BEFORE STATEMENT handler przydzieli tabelę PL/SQL do przechowywania wielu liczb. W tym przypadku liczbami, które mają być przechowywane w tabeli PL/SQL będą wartości TABLE2_ID z TABLE1. (Tabela PL/SQL jest używana zamiast na przykład tablicy, ponieważ tabela może przechowywać różną liczbę wartości, podczas gdy gdybyśmy używali tablicy, musielibyśmy z góry wiedzieć, ile liczb będziemy musieli przechowywać. Nie możemy z góry wiedzieć, na ile wierszy wpłynie dana instrukcja, więc używamy tabeli PL/SQL).

Gdy AFTER EACH ROW Osiągnięto punkt czasowy i stwierdziliśmy, że przetwarzana instrukcja to INSERT, wyzwalacz po prostu kontynuuje działanie i wykonuje niezbędną aktualizację do tabeli TABLE2, ponieważ nie spowoduje to problemu. Jeśli jednak wykonywane jest polecenie DELETE, wyzwalacz zapisuje TABLE1.TABLE2_ID w przydzielonej wcześniej tabeli PL/SQL. Gdy AFTER STATEMENT w końcu osiągnięty został punkt czasowy, przydzielona wcześniej tabela PL/SQL jest iterowana i dla każdego znalezionego identyfikatora TABLE2_ID przeprowadzana jest odpowiednia aktualizacja.

Dokumentacja tutaj.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle:W PRZYPADKU AKTUALIZACJI ZDUPLIKOWANEGO KLUCZA

  2. Jak korzystać z funkcji Oracle LITAGG

  3. Co to jest operator konkatenacji ciągów w Oracle?

  4. Jak wyświetlić plan wyjaśniania w programie Oracle SQL Developer?

  5. Wyzwanie testowania bazy danych Oracle — Porównaj dane schematu