在表格中计算学生状态的触发器

时间:2019-07-05 23:27:37

标签: oracle triggers

我需要构造一个触发器,以便每次将新行与数据(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

我被困在如何创建此触发器以自动计算

2 个答案:

答案 0 :(得分:1)

要获取状态值,请考虑使用VIEW(而不是触发器)。您已经提到了RULES表(包含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映射。为简单起见,我们只是将具有偶数学生身份的学生“注册”到uni 1中,将具有奇数学生身份的学生进入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定义的RULES给出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

答案 1 :(得分:0)

使用BEFORE INSERT触发器来处理传入记录值,然后再将其写入。这样一来,您就可以基于传入的SUBJECT.STATUS列值来设置SUBJECT

触发器使用: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声明。如果对此有任何疑问,请留下笔记,我们将很乐意解释。