我需要构造一个触发器,以便每次将新行与数据(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
我被困在如何创建此触发器以自动计算
答案 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.
答案 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_GRADE
和MINIMUM_FREQ
。如果您实际的列名不同,请改用它们。
代码还使用Oracle %TYPE
属性基于基础列类型定义变量类型。因此,如果SUBJECT.STATUS
列为VARCHAR2(2)
,则stat
变量将为VARCHAR2(2)
。如果是CHAR(2)
,则stat
将是CHAR(2)
。如果是VARCHAR2(500)
,则stat
将是VARCHAR2(500)
。依此类推。
我没有在顶部解释CREATE TRIGGER
声明。如果对此有任何疑问,请留下笔记,我们将很乐意解释。