Een paar problemen in willekeurige volgorde.
Ten eerste moet u in de hoofdtekst van een trigger op rijniveau :new
. gebruiken en :old
om te verwijzen naar de nieuwe en oude records. De leidende dubbele punt is noodzakelijk. Dus je WHERE
clausule zou moeten zijn
WHERE PROJECTID = :new.PROJECTID
Ten tweede, als u uw CREATE TRIGGER
. gebruikt in SQL*Plus kunt u een lijst met fouten en waarschuwingen krijgen met behulp van de SHOW ERRORS
commando, d.w.z.
SQL> show errors
U kunt ook de DBA_ERRORS
. opvragen tabel (of ALL_ERRORS
of USER_ERRORS
afhankelijk van uw privilegeniveau), maar dat is niet iets waar u normaal gesproken uw toevlucht tot hoeft te nemen.
Ten derde, ervan uitgaande dat de syntaxisfouten worden gecorrigeerd, krijgt u een muterende tabelfout
als je deze logica gebruikt. Een trigger op rijniveau in tabel A (TPM_TRAININGPLAN
in dit geval) kan geen query uitvoeren op tabel A omdat de tabel zich mogelijk in een inconsistente staat bevindt. Je kunt dat omzeilen, zoals Tim in zijn artikel laat zien, door een pakket met een verzameling te maken, die verzameling te initialiseren in een trigger voor de instructie, de gegevens in de verzameling in een trigger op rijniveau te vullen en vervolgens de gewijzigde rijen te verwerken in een after-statement-trigger. Dat is echter een behoorlijke hoeveelheid complexiteit om aan het systeem toe te voegen, aangezien u meerdere verschillende objecten moet beheren.
Over het algemeen kunt u deze logica beter implementeren als onderdeel van de API die u gebruikt om het TPM_TRAININGPLAN
te manipuleren. tafel. Als dat een opgeslagen procedure is, is het veel logischer om de logica toe te passen om TPM_PROJECT
bij te werken in die opgeslagen procedure in plaats van het in een trigger te plaatsen. Het is notoir pijnlijk om te proberen een applicatie te debuggen die veel logica heeft ingebed in triggers, omdat dat het erg moeilijk maakt voor ontwikkelaars om precies te volgen welke bewerkingen worden uitgevoerd. U kunt ook de TRAININGDELIVERYSTART
. verwijderen kolom uit TPM_PROJECT
tabel en bereken gewoon de minimale startdatum tijdens runtime.
Ten vierde, als je trigger wordt geactiveerd bij invoegingen, updates en verwijderingen, kun je niet zomaar verwijzen naar :new
waarden. :new
is geldig voor invoegingen en updates, maar het wordt NULL als u een verwijdering uitvoert. :old
is geldig voor verwijderingen en updates, maar wordt NULL als u een invoeging uitvoert. Dat betekent dat je waarschijnlijk logica nodig hebt in de trant van (verwijzend naar de pakketoplossing van 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;