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;