sql >> Database >  >> RDS >> Oracle

Oracle - Probleem bij het maken van een trigger die een andere tabel bijwerkt

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;


  1. WEEKOFYEAR(NOW()) vs WEEK('2018-05-1') - de huidige datum

  2. Hoe PostgreSQL in een Docker-container te controleren:deel twee

  3. Hoe de tabelopslag-engine van MyISAM naar InnoDB te veranderen?

  4. Favoriete trucs voor het afstemmen van prestaties