Alcuni problemi in ordine sparso.
Innanzitutto, nel corpo di un attivatore a livello di riga, devi utilizzare :new
e :old
per fare riferimento ai record nuovi e vecchi. I due punti iniziali sono necessari. Quindi il tuo WHERE
la clausola dovrebbe essere
WHERE PROJECTID = :new.PROJECTID
Secondo, se stai eseguendo il tuo CREATE TRIGGER
in SQL*Plus, puoi ottenere un elenco degli errori e degli avvisi utilizzando SHOW ERRORS
comando, cioè
SQL> show errors
Puoi anche interrogare DBA_ERRORS
tabella (o ALL_ERRORS
o USER_ERRORS
a seconda del tuo livello di privilegio) ma non è qualcosa a cui normalmente devi ricorrere.
Terzo, supponendo che gli errori di sintassi vengano corretti, otterrai una mutante errore di tabella
se usi questa logica Un trigger a livello di riga nella tabella A (TPM_TRAININGPLAN
in questo caso) non può interrogare la tabella A perché la tabella potrebbe trovarsi in uno stato incoerente. Puoi aggirare il problema, come mostra Tim nel suo articolo, creando un pacchetto con una raccolta, inizializzando tale raccolta in un trigger di istruzione before, popolando i dati nella raccolta in un trigger a livello di riga e quindi elaborando le righe modificate in un trigger di istruzione dopo. Questa è una discreta quantità di complessità da aggiungere al sistema, tuttavia, dal momento che dovrai gestire più oggetti diversi.
In generale, faresti meglio a implementare questa logica come parte di qualsiasi API che utilizzi per manipolare il TPM_TRAININGPLAN
tavolo. Se si tratta di una procedura memorizzata, ha molto più senso inserire la logica per aggiornare TPM_PROJECT
in quella procedura memorizzata anziché inserirla in un trigger. È notoriamente doloroso provare a eseguire il debug di un'applicazione che ha molta logica incorporata nei trigger perché ciò rende molto difficile per gli sviluppatori seguire esattamente quali operazioni vengono eseguite. In alternativa, puoi rimuovere TRAININGDELIVERYSTART
colonna da TPM_PROJECT
tabella e calcola semplicemente la data di inizio minima in fase di esecuzione.
In quarto luogo, se il tuo trigger si attiva su inserimenti, aggiornamenti ed eliminazioni, non puoi semplicemente fare riferimento a :new
i valori. :new
è valido per inserimenti e aggiornamenti ma sarà NULL se si esegue un'eliminazione. :old
è valido per eliminazioni e aggiornamenti ma sarà NULL se stai eseguendo un inserimento. Ciò significa che probabilmente devi avere una logica sulla falsariga di (riferendosi alla soluzione del pacchetto di Tim)
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;