Quelques problèmes sans ordre particulier.
Tout d'abord, dans le corps d'un déclencheur au niveau de la ligne, vous devez utiliser :new et :old pour référencer les nouveaux et anciens enregistrements. Le premier côlon est nécessaire. Donc, votre WHERE clause devrait être
WHERE PROJECTID = :new.PROJECTID
Deuxièmement, si vous exécutez votre CREATE TRIGGER dans SQL*Plus, vous pouvez obtenir une liste des erreurs et des avertissements en utilisant le SHOW ERRORS commande, c'est-à-dire
SQL> show errors
Vous pouvez également interroger le DBA_ERRORS table (ou ALL_ERRORS ou USER_ERRORS en fonction de votre niveau de privilège) mais ce n'est pas quelque chose auquel vous devez normalement recourir.
Troisièmement, en supposant que les erreurs de syntaxe soient corrigées, vous obtiendrez un mutating erreur de tableau
si vous utilisez cette logique. Un déclencheur au niveau de la ligne sur la table A (TPM_TRAININGPLAN dans ce cas) ne peut pas interroger la table A car la table peut être dans un état incohérent. Vous pouvez contourner cela, comme le montre Tim dans son article, en créant un package avec une collection, en initialisant cette collection dans un déclencheur d'instruction avant, en remplissant les données de la collection dans un déclencheur au niveau de la ligne, puis en traitant les lignes modifiées dans un déclencheur d'instruction après. C'est une quantité décente de complexité à ajouter au système, cependant, puisque vous devrez gérer plusieurs objets différents.
En règle générale, vous feriez mieux d'implémenter cette logique dans le cadre de l'API que vous utilisez pour manipuler le TPM_TRAININGPLAN table. S'il s'agit d'une procédure stockée, il est beaucoup plus logique de mettre la logique à jour TPM_PROJECT dans cette procédure stockée plutôt que de la mettre dans un déclencheur. Il est notoirement pénible d'essayer de déboguer une application qui a beaucoup de logique intégrée dans les déclencheurs car cela rend très difficile pour les développeurs de suivre exactement quelles opérations sont effectuées. Vous pouvez également supprimer le TRAININGDELIVERYSTART colonne de TPM_PROJECT table et calculez simplement la date de début minimale au moment de l'exécution.
Quatrièmement, si votre déclencheur se déclenche lors d'insertions, de mises à jour et de suppressions, vous ne pouvez pas simplement référencer :new valeurs. :new est valide pour les insertions et les mises à jour, mais il sera NULL si vous effectuez une suppression. :old est valide pour les suppressions et les mises à jour mais va être NULL si vous faites une insertion. Cela signifie que vous devez probablement avoir une logique du type (référence à la solution de package de 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;