Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle - Problème lors de la création d'un déclencheur qui met à jour une autre table

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;