创建PL/SQL触发器:基于DAILY_ATT表计算各学生总出勤数
实现自动计算出勤总数的PL/SQL触发器
没问题,我来帮你搞定这个需求!你已经完成了数据表的创建和测试数据插入,接下来我们只需要编写一个PL/SQL触发器,就能让TOTAL_ATT表自动同步DAILY_ATT中每个学生的总出勤数了。
触发器实现思路
我们需要让触发器在DAILY_ATT表发生插入、更新、删除操作时都能触发,然后针对每个受影响的roll_no,计算其累计出勤数,并同步到TOTAL_ATT表。这里用MERGE语句来处理“存在则更新,不存在则插入”的场景,同时处理删除后无剩余记录时的清理工作。
完整触发器代码
CREATE OR REPLACE TRIGGER update_total_attendance AFTER INSERT OR UPDATE OR DELETE ON daily_att FOR EACH ROW BEGIN -- 同步对应roll_no的总出勤数:存在则更新,不存在则插入 MERGE INTO total_att ta USING ( SELECT :new.roll_no AS roll_no, SUM(attendance) AS total FROM daily_att WHERE roll_no = :new.roll_no ) da ON (ta.roll_no = da.roll_no) WHEN MATCHED THEN UPDATE SET ta.total_attendance = da.total WHEN NOT MATCHED THEN INSERT (roll_no, total_attendance) VALUES (da.roll_no, da.total); -- 若执行删除操作,检查该roll_no是否还有剩余出勤记录,没有则删除总表中的对应条目 IF DELETING THEN DELETE FROM total_att WHERE roll_no = :old.roll_no AND NOT EXISTS ( SELECT 1 FROM daily_att WHERE roll_no = :old.roll_no ); END IF; END; /
代码说明
- 触发时机与事件:
AFTER INSERT OR UPDATE OR DELETE ON daily_att指定了触发器在DAILY_ATT表的三种数据变更操作后触发,FOR EACH ROW表示每一行数据变更都会触发一次。 - MERGE语句:这是核心逻辑,通过子查询计算当前
roll_no的总出勤数,然后和TOTAL_ATT表匹配:- 如果已有该学生的记录,就更新总出勤数;
- 如果没有,就插入一条新的总出勤记录。
- 删除后的清理:当执行删除操作时,额外检查该学生在
DAILY_ATT中是否还有剩余记录,如果没有,就把TOTAL_ATT中对应的记录删掉,避免无效数据残留。
测试验证
你可以通过以下操作验证触发器是否正常工作:
- 插入新出勤记录:
执行后查询INSERT INTO daily_att VALUES(1, 'SCIENCE', 1, '05-MAY-18');TOTAL_ATT,应该能看到roll_no=1的total_attendance更新为2(0+1+1)。 - 更新出勤记录:
查询UPDATE daily_att SET attendance=1 WHERE roll_no=1 AND subject='MATHS';TOTAL_ATT,total_attendance会变为3(1+1+1)。 - 删除所有该学生的记录:
查询DELETE FROM daily_att WHERE roll_no=1;TOTAL_ATT,roll_no=1的条目会被自动删除。
内容的提问来源于stack exchange,提问作者cmcodes
相关产品推荐
相关产品推荐

