【问题标题】:TRIGGER that calculates the STATUS of a student in a table计算表中学生状态的触发器
【发布时间】:2019-07-07 16:46:02
【问题描述】:

我需要构造一个触发器,以便每次将带有数据(STDID、SUBJID、SEMESTER / YEAR、GRADE、FREQ)的新行插入到 SUBJECT 表中时,自动计算并输入 STATUS 字段的值.审批规则在 RULES 表中,其架构如下。该表只有一行,但带来了可以动态更改的便利。例如,在我的大学的情况下,它与数据 5.0(最低成绩)和 75%(最低频率)有一条线,但在另一所大学可能是 7.0 和 80%。 表规则(minGRADE、minFREQ)

我有两张桌子:

主题

STDID   SUBJID   SEMESTER_YEAR  GRADE    FREQ   STATUS
1111    2         2/2018          6       75    ok
1111    13        2/2018          7       100   ok
1111    4         1/2018          5       90    ok
1111    7         1/2018          10      95    ok
1111    9         2/2018          8       75    ok
1122    2         2/2017          3       75    no
1122    13        2/2017          5       100   ok
1122    4         1/2017          5       90    ok
1122    7         1/2017          10      95    ok
1122    9         2/2017          8       75    ok
1113    2         2/2018          6       75    ok
1113    13        2/2018          7       100   ok
1113    4         1/2018          5       90    ok
1113    7         1/2018          4       95    no
1113    9         2/2018          8       75    ok
1132    2         2/2018          3       75    no
1132    13        2/2018          7       100   ok
1132    4         1/2018          5       90    ok
1132    7         1/2018          4       95    no
1132    9         2/2018          8       75    ok

另一个:学生

            STDID     NAME      DATA_NASC
            1111    gabriel     12-APR-70
            1112    pedro       12-JUN-70
            1113    lucas       12-MAR-70
            1114    mariana     12-FEB-70
            1115    klemer      12-SEP-70
            1116    jose        12-DEC-70
            1117    vitor       12-NOV-70
            1118    artur       12-APR-70
            1119    bia         12-NOV-70
            1120    julia       12-MAR-70
            1121    rafaela     12-JAN-70
            1122    augusto     12-FEB-70
            1123    eneas       12-JUL-70
            1124    zezinho     12-APR-70
            1125    hugo        12-APR-70
            1126    matheus     12-APR-70
            1127    diana       12-APR-70
            1128    andre       12-APR-70
            1129    reco        12-APR-70

我不知道如何创建此触发器以自动计算

【问题讨论】:

    标签: oracle triggers


    【解决方案1】:

    要获取 STATUS 值,请考虑使用 VIEW(而不是触发器)。您提到了一个规则表(包含 minGRADE 等)。如果您使用的是 Oracle 12c(或更新版本),您可以使用 LATERAL JOIN 来动态“计算”STATUS 列的值。

    规则表

    create table rules ( univid, mingrade, minfreq )
    as
    select 1, 5, 75 from dual ;
    

    使用您的 SUBJECT 表的定义和数据,我们可以使用此查询来获取所需的结果(注意:没有触发器)。我们从 RULES 表中获取 MINGRADE 和 MINFREQ,并在主查询的 CASE 中使用这些值(通过 LATERAL JOIN)。

    select S.*
    , case
        when grade >= mingrade and freq >= minfreq then 'ok'
        else 'not ok'
      end as status
    from subject S, lateral ( 
      select mingrade, minfreq from rules where univid = 1
    );
    
    
    -- result
         STDID     SUBJID SEMEST      GRADE       FREQ STATUS
    ---------- ---------- ------ ---------- ---------- ------
          1111          2 2/2018          6         75 ok    
          1111         13 2/2018          7        100 ok    
          1111          4 1/2018          5         90 ok    
          1111          7 1/2018         10         95 ok    
          1111          9 2/2018          8         75 ok    
          1122          2 2/2017          3         75 not ok
          1122         13 2/2017          5        100 ok    
          1122          4 1/2017          5         90 ok    
          1122          7 1/2017         10         95 ok    
          1122          9 2/2017          8         75 ok    
          1113          2 2/2018          6         75 ok    
          1113         13 2/2018          7        100 ok    
          1113          4 1/2018          5         90 ok    
          1113          7 1/2018          4         95 not ok
          1113          9 2/2018          8         75 ok    
          1132          2 2/2018          3         75 not ok
          1132         13 2/2018          7        100 ok    
          1132          4 1/2018          5         90 ok    
          1132          7 1/2018          4         95 not ok
          1132          9 2/2018          8         75 ok    
    
    20 rows selected.
    

    我们在这里假设所有学生都被大学 1 录取 - 请参阅 DBfiddle

    如果您要处理多个规则(针对多个大学),您仍然可以使用这种方法 - 无需编写触发器。在下面的示例中,我们 {1} 创建了一个登记表,其中包含 STUDENT-UNIVERSITY 映射。为简单起见,我们只是将学生 ID 为偶数的学生“注册”到 uni 1,学生 ID 为奇数的学生进入 uni 2。{2} 我们将 uni 2 的规则添加到 RULES 表中。

    -- ENROLMENTS table
    create table enrolments( studentid, universityid )
    as
    select
      stdid, mod( stdid, 2 ) + 1
    from subject ;
    
    -- add a RULE
    insert into rules ( univid, mingrade, minfreq ) values ( 2, 7, 80 ) ;
    
    -- the RULES table now contains ...
    SQL> select * from rules ;
    
        UNIVID   MINGRADE    MINFREQ
    ---------- ---------- ----------
             1          5         75
             2          7         80
    

    以下查询将分别根据为 uni 1 和 uni 2 定义的规则为我们提供 STATUS 值。 (如果有更多大学/规则,只需添加招生和规则。没有触发器。)

    查询

    select unique
      S.*
    , case
        when grade >= mingrade and freq >= minfreq then 'ok'
        else 'not ok'
      end as status
    , R.univid   as "R.uni"        -- output: the universityid
    , R.mingrade as "R.mingrade"   -- and the rules
    , R.minfreq  as "R.minfreq"    -- for both universities - just for "illustration"
    from subject S
    , lateral(
      select universityid from enrolments where S.stdid = studentid
    ) E 
    join rules R on E.universityid = R.univid
    ;
    

    结果

    STDID  SUBJID  SEMESTER_YEAR  GRADE  FREQ  STATUS  R.uni  R.mingrade  R.minfreq  
    1122   13      2/2017         5      100   ok      1      5           75         
    1122   2       2/2017         3      75    not ok  1      5           75         
    1113   9       2/2018         8      75    not ok  2      7           80         
    1132   9       2/2018         8      75    ok      1      5           75         
    1113   4       1/2018         5      90    not ok  2      7           80         
    1113   13      2/2018         7      100   ok      2      7           80         
    1132   7       1/2018         4      95    not ok  1      5           75         
    1132   4       1/2018         5      90    ok      1      5           75         
    1132   2       2/2018         3      75    not ok  1      5           75         
    1111   2       2/2018         6      75    not ok  2      7           80         
    1122   7       1/2017         10     95    ok      1      5           75         
    1113   7       1/2018         4      95    not ok  2      7           80         
    1111   4       1/2018         5      90    not ok  2      7           80         
    1111   7       1/2018         10     95    ok      2      7           80         
    1111   13      2/2018         7      100   ok      2      7           80         
    1122   9       2/2017         8      75    ok      1      5           75         
    1111   9       2/2018         8      75    not ok  2      7           80         
    1132   13      2/2018         7      100   ok      1      5           75         
    1113   2       2/2018         6      75    not ok  2      7           80         
    1122   4       1/2017         5      90    ok      1      5           75         
    
    
    20 rows selected. 
    

    DBfiddle here.

    【讨论】:

      【解决方案2】:

      使用BEFORE INSERT 触发器在写入之前处理传入的记录值。这使您可以根据传入的SUBJECT 列值设置SUBJECT.STATUS

      触发器使用:NEW 别名来表示即将用INSERT 语句写入的列值。您可以查询或更改传入的值。此触发器同时执行以下操作:查询等级和频率,并更改状态。

      CREATE OR REPLACE TRIGGER SUBJECT_STATUS
        BEFORE INSERT
        ON SUBJECT
        FOR EACH ROW
      
      DECLARE
        stat SUBJECT.STATUS%TYPE;
        minGrade RULES.MINIMUM_GRADE%TYPE;
        minFreq RULE.MINIMUM_FREQ%TYPE;
      
      BEGIN
      
        -- Read minimum grade and frequency into variables
        SELECT MINIMUM_GRADE, MINIMUM_FREQ
          INTO minGrade, minFreq
          FROM RULES;
      
        IF :NEW.GRADE >= minGrade AND :NEW.FREQ >= minFreq THEN
          -- If the student achieves minimum grade and frequency then status is "ok"
          :NEW.STATUS := 'ok';
        ELSE
          -- If not then status is "no"
          :NEW.STATUS := 'no';
        END IF;
      
      END;
      

      注意事项:

      • 此代码假定您的RULES 表具有分别用于最低等级和频率的MINIMUM_GRADEMINIMUM_FREQ 列。如果您的实际列名不同,请改用它们。

      • 代码还使用Oracle %TYPE 属性来定义基于底层列类型的变量类型。因此,如果SUBJECT.STATUS 列是VARCHAR2(2),那么stat 变量将为VARCHAR2(2)。如果是CHAR(2),那么stat 将是CHAR(2)。如果是VARCHAR2(500),那么stat 将是VARCHAR2(500)。以此类推。

      • 我没有解释顶部的CREATE TRIGGER 声明。如果您对此有任何疑问,请留言,我很乐意为您解释。

      【讨论】:

        猜你喜欢
        • 2015-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        • 2021-07-26
        • 1970-01-01
        • 2013-09-02
        • 2012-03-10
        相关资源
        最近更新 更多