Voici le problème:
Créez un déclencheur qui empêche toute modification de la relation de prise qui ferait passer la note moyenne globale dans une classe donnée en dessous de 2,5. Remarque: ce déclencheur n'est pas destiné à traiter la moyenne moyenne d'un étudiant donné, mais plutôt à la note moyenne de toutes les notes attribuées dans une classe donnée.
Voici le schéma:
Student-schema =(studentnum, name, standing, gpa, major)
Class-schema = (schedulenum, semester, department, classnum, days, time, place, enrollment)
Instructor-schema = (name, department, office)
Teaches-schema = (name, schedulenum, semester)
Taking-schema = (studentnum, schedulenum, semester, grade)
Je passe un mauvais moment avec ces déclencheurs, mais voici ma tentative pour que cela fonctionne:
CREATE OR REPLACE TRIGGER stopChange
AFTER UPDATE OR INSERT OR DELETE ON taking
REFERENCING OLD AS old
NEW AS new
FOR EACH ROW
DECLARE
grd_avg taking.grade%TYPE;
BEGIN
SELECT AVG(grade)
INTO grd_avg
FROM taking
WHERE studentnum = :new.studentnum
AND schedulenum = :new.schedulenum
AND semester = :new.semester;
IF grd_avg < 2.5 THEN
UPDATE taking
SET grade = :old.grade
WHERE studentnum = :old.studentnum
AND schedulenum = :old.schedulenum
AND semester = :old.semester;
END IF;
END;
/
Je fais évidemment quelque chose de mal parce que quand je vais ensuite mettre à jour ou supprimer un tuple, j'obtiens le message d'erreur:
ERROR at line 1:
ORA-04091: table TAKING is mutating, trigger/function may not see it
ORA-06512: at "STOPCHANGE", line 6
ORA-04088: error during execution of trigger 'STOPCHANGE'
Aucun conseil? J'utilise Oracle.
Je pense que vous pouvez résoudre ce problème en réécrivant ceci en tant que déclencheur avant, plutôt que déclencheur après. Cependant, cela pourrait être un peu compliqué pour les insertions et les suppressions. L'idée est:
CREATE OR REPLACE TRIGGER stopChange
BEFORE UPDATE OR INSERT OR DELETE ON taking
REFERENCING OLD AS old
NEW AS new
FOR EACH ROW
DECLARE
grd_avg taking.grade%TYPE;
BEGIN
SELECT (SUM(grade) - oldgrade + new.grade) / count(*)
INTO grd_avg
FROM taking
WHERE studentnum = :new.studentnum
AND schedulenum = :new.schedulenum
AND semester = :new.semester;
IF grd_avg < 2.5 THEN
new.grade = old.grade
END IF;
END;
utilisez cette déclaration dans DECLARE
, cela fonctionnera.
pragma autonomous_transaction;
Vous devez d’abord connaître les déclencheurs, l’erreur de table de mutation et les déclencheurs composés: http://docs.Oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005
Votre déclencheur est AFTER UPDATE OR INSERT OR DELETE. Cela signifie que si vous exécutez les instructions UPDATE OR INSERT OR DELETE sur cette table, le déclencheur se déclenchera. Mais vous essayez de mettre à jour la même table à nouveau dans votre déclencheur, ce qui est compl. faux. C'est pourquoi vous obtenez l'erreur. Vous ne pouvez pas modifier la même table sur laquelle le déclencheur est activé. Le déclencheur a pour but de se déclencher automatiquement lorsque la table est mise à jour, insérée ou supprimée dans votre cas. Ce dont vous avez besoin est une procédure, pas un déclencheur.
Même nous avons fini avec le même problème dans notre projet. Mais après avoir cherché dans quelques forums Oracle, nous avons trouvé la solution ci-dessous.
1) Enregistrez les données de l'ancienne/nouvelle colonne dans une table temporaire sous forme de pat du déclencheur de niveau ligne . 2) Écrivez un déclencheur de niveau instruction et utilisez les données enregistrées à l'étape 1.
Cela résoudrait le problème, je pense.
J'ai eu le même problème et j'ai remarqué que si vous faites un select sur la même table, vous mettez/vous obtiendrez ce problème . Vous pouvez supprimer FOR EACH ROW Ou utiliser le données dans: Nouveau pour effectuer le calcul (si possible) puis effectuer la mise à jour.
Dans votre cas, il serait plus judicieux d'utiliser une table distincte pour obtenir la moyenne moyenne par semestre.