Několik problémů v žádném konkrétním pořadí.
Nejprve v těle spouštěče na úrovni řádku musíte použít :new
a :old
odkazovat na nové a staré záznamy. Úvodní dvojtečka je nezbytná. Takže vaše WHERE
klauzule by musela být
WHERE PROJECTID = :new.PROJECTID
Za druhé, pokud používáte CREATE TRIGGER
v SQL*Plus můžete získat seznam chyb a varování pomocí SHOW ERRORS
příkaz, tj.
SQL> show errors
Můžete také zadat dotaz na DBA_ERRORS
tabulka (nebo ALL_ERRORS
nebo USER_ERRORS
v závislosti na vaší úrovni oprávnění), ale to není něco, k čemu byste se normálně museli uchýlit.
Za třetí, za předpokladu, že budou opraveny syntaktické chyby, dostanete mutující chyba tabulky
pokud použijete tuto logiku. Spouštěč na úrovni řádku v tabulce A (TPM_TRAININGPLAN
v tomto případě) nelze dotazovat tabulku A, protože tabulka může být v nekonzistentním stavu. Jak ukazuje Tim ve svém článku, můžete to obejít tak, že vytvoříte balíček s kolekcí, inicializujete tuto kolekci ve spouštěči příkazu before, naplníte data v kolekci ve spouštěči na úrovni řádků a poté zpracujete upravené řádky v spouštěč po příkazu. To je však slušná míra složitosti, kterou je třeba do systému přidat, protože budete muset spravovat více různých objektů.
Obecně by bylo lepší implementovat tuto logiku jako součást jakéhokoli API, které používáte k manipulaci s TPM_TRAININGPLAN
stůl. Pokud se jedná o uloženou proceduru, je mnohem smysluplnější použít logiku pro aktualizaci TPM_PROJECT
v této uložené proceduře spíše než její vložení do spouštěče. Je notoricky bolestivé pokoušet se ladit aplikaci, která má spoustu logiky zabudované do triggerů, protože to vývojářům velmi ztěžuje přesně sledovat, jaké operace se provádějí. Alternativně můžete odstranit TRAININGDELIVERYSTART
sloupec z TPM_PROJECT
a vypočítejte minimální počáteční datum za běhu.
Za čtvrté, pokud se spouštěč spustí při vložení, aktualizaci a odstranění, nemůžete jednoduše odkazovat na :new
hodnoty. :new
je platný pro vložení a aktualizace, ale pokud provádíte mazání, bude mít hodnotu NULL. :old
je platný pro mazání a aktualizace, ale pokud provádíte vkládání, bude mít hodnotu NULL. To znamená, že pravděpodobně potřebujete mít logiku v souladu s (odkazem na Timovo řešení balíčku)
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;