[英]Create a trigger that automatically assign grade in PL/SQL
I want to make a trigger that when I update student's mark in a table.. then it will automatically assign a grade.我想触发一个触发器,当我在表格中更新学生的分数时......然后它会自动分配一个成绩。
CREATE OR ALTER TRIGGER calculate_grade
AFTER INSERT OR UPDATE ON student_subject
BEGIN
UPDATE student_subject SET grade =
CASE
WHEN (new.firstterm+new.secondterm) >= 80 THEN 'A'
WHEN (new.firstterm+new.secondterm) >= 65 AND (new.firstterm+new.secondterm) < 80 THEN 'B'
WHEN (new.firstterm+new.secondterm) >= 50 AND (new.firstterm+new.secondterm) < 65 THEN 'C'
WHEN (new.firstterm+new.secondterm) >= 40 AND (new.firstterm+new.secondterm) < 50 THEN 'D'
WHEN (new.firstterm+new.secondterm) >= 20 AND (new.firstterm+new.secondterm) < 40 THEN 'E'
ELSE 'F'
END
END
but it found it errors.. how do I fix it但它发现它错误..我该如何解决它
For this use case I would recommend using virtual column .对于这个用例,我建议使用virtual column 。 You will save on space (only metadata are stored about the column) and grade will be always in sync (someone can disable trigger for a while and this could cause problems with data integrity using trigger based approach).
您将节省空间(仅存储有关列的元数据)并且成绩将始终保持同步(有人可以禁用触发器一段时间,这可能会导致使用基于触发器的方法导致数据完整性问题)。 DML on the table will be also faster.
桌上的DML也会更快。
create table t(
id number primary key,
firstterm number,
secondterm number,
grade char(1) generated always as (
case
when firstterm + secondterm >= 80 then 'A'
when firstterm + secondterm >= 65 then 'B'
when firstterm + secondterm >= 50 then 'C'
when firstterm + secondterm >= 40 then 'D'
when firstterm + secondterm >= 20 then 'E'
when firstterm + secondterm >= 0 then 'F'
else null
end
) virtual
)
You cannot Update the table that fired the trigger, you are already in the process of updating (or inserting) it so I'm guessing you getting a "ORA-04091: table is mutating" exception.您无法更新触发触发器的表,您已经在更新(或插入)它的过程中,所以我猜您收到“ORA-04091:表正在变异”异常。 If not you will.
如果不是,你会的。 You could be getting compile errors.
您可能会遇到编译错误。 But updating is not necessary.
但是没有必要更新。 Instead of attempting update just use assignment.
而不是尝试更新只是使用分配。 Also references to New and/or Old require a leading colon (:).
对 New 和/或 Old 的引用也需要前导冒号 (:)。
create or alter trigger calculate_grade
after insert or update on student_subject
begin
:new.grade :=
case
when (:new.firstterm+:new.secondterm) >= 80 then 'A'
when (:new.firstterm+:new.secondterm) >= 65 and (:new.firstterm+:new.secondterm) < 80 then 'B';
when (:new.firstterm+:new.secondterm) >= 50 and (:new.firstterm+:new.secondterm) < 65 then 'C';
when (:new.firstterm+:new.secondterm) >= 40 and (:new.firstterm+:new.secondterm) < 50 then 'D';
when (:new.firstterm+:new.secondterm) >= 20 and (:new.firstterm+:new.secondterm) < 40 then 'E';
else 'F'
end;
end ;
I would suggest a before trigger:我会建议一个前触发器:
CREATE OR ALTER TRIGGER calculate_grade
BEFORE INSERT OR UPDATE ON student_subject
BEGIN
SELECT (CASE WHEN (:new.firstterm + :new.secondterm) >= 80 THEN 'A'
WHEN (:new.firstterm + :new.secondterm) >= 65 THEN 'B'
WHEN (:new.firstterm + :new.secondterm) >= 50 THEN 'C'
WHEN (:new.firstterm + :new.secondterm) >= 40 THEN 'D'
WHEN (:new.firstterm + :new.secondterm) >= 20 THEN 'E'
ELSE 'F'
END)
INTO :NEW.GRADE
FROM DUAL;
END;
Note that the CASE
logic is evaluated in order, so you don't have to use BETWEEN
for the conditions.请注意,
CASE
逻辑是按顺序计算的,因此您不必对条件使用BETWEEN
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.