简体   繁体   English

创建一个在 PL/SQL 中自动分配成绩的触发器

[英]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
)

sqlfiddle sqlfiddle

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM