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

Oracle — Problem z tworzeniem wyzwalacza, który aktualizuje inną tabelę

Kilka problemów w przypadkowej kolejności.

Najpierw w treści wyzwalacza na poziomie wiersza musisz użyć :new i :old odwoływać się do nowych i starych rekordów. Konieczny jest wiodący dwukropek. Więc Twój WHERE klauzula musiałaby być

WHERE PROJECTID = :new.PROJECTID

Po drugie, jeśli używasz CREATE TRIGGER w SQL*Plus możesz uzyskać listę błędów i ostrzeżeń za pomocą SHOW ERRORS polecenie, tj.

SQL> show errors

Możesz również zapytać o DBA_ERRORS tabela (lub ALL_ERRORS lub USER_ERRORS w zależności od poziomu uprawnień), ale nie jest to coś, do czego zwykle trzeba się uciekać.

Po trzecie, zakładając, że błędy składni zostaną poprawione, otrzymasz mutację błąd tabeli jeśli użyjesz tej logiki. Wyzwalacz na poziomie wiersza w tabeli A (TPM_TRAININGPLAN w tym przypadku) nie można wykonać zapytania do tabeli A, ponieważ tabela może być w niespójnym stanie. Można to obejść, jak pokazuje Tim w swoim artykule, tworząc pakiet z kolekcją, inicjując tę ​​kolekcję w wyzwalaczu instrukcji before, wypełniając dane w kolekcji w wyzwalaczu na poziomie wiersza, a następnie przetwarzając zmodyfikowane wiersze w wyzwalacz po oświadczeniu. Jest to jednak przyzwoita ilość złożoności, którą można dodać do systemu, ponieważ będziesz musiał zarządzać wieloma różnymi obiektami.

Ogólnie rzecz biorąc, lepiej byłoby zaimplementować tę logikę jako część dowolnego interfejsu API, którego używasz do manipulowania TPM_TRAININGPLAN stół. Jeśli jest to procedura składowana, znacznie bardziej sensowne jest umieszczenie logiki aktualizacji TPM_PROJECT w tej procedurze składowanej zamiast umieszczania jej w wyzwalaczu. Bardzo bolesna jest próba debugowania aplikacji, która ma wiele logiki osadzonych w wyzwalaczach, ponieważ bardzo utrudnia to programistom dokładne śledzenie wykonywanych operacji. Alternatywnie możesz usunąć TRAININGDELIVERYSTART kolumna z TPM_PROJECT tabeli i po prostu oblicz minimalną datę rozpoczęcia w czasie wykonywania.

Po czwarte, jeśli wyzwalacz uruchamia się przy wstawianiu, aktualizowaniu i usuwaniu, nie możesz po prostu odwołać się do :new wartości. :new jest prawidłowy dla wstawek i aktualizacji, ale będzie NULL, jeśli robisz usuwanie. :old jest prawidłowy dla usuwania i aktualizacji, ale będzie miał wartość NULL, jeśli robisz wstawianie. Oznacza to, że prawdopodobnie musisz mieć logikę zgodnie z (odnosząc się do rozwiązania pakietu Tima)

BEGIN
  IF inserting 
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
  ELSIF updating
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
  ELSIF deleting
  THEN
    trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
  END IF;
END;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zdarzenie oczekiwania:zmiana rozmiaru deskryptora asynchronicznego

  2. Konwertuj tablicę Varchar2 na Char w Oracle

  3. Wykonywanie procesu Oracle Stored jako inny użytkownik

  4. Dlaczego ORACLE nie zezwala na kolejne znaki nowego wiersza w poleceniach?

  5. Aktualizowanie widoku sprzężenia bez otrzymywania błędu niezachowania klucza