在我的
University
数据库中,我有 Student
、Takes
和 Course
表:
Student
(ID、姓名、部门名称、总学分)Takes
(学生 ID、课程 ID、部门 ID、学期、年份、年级)Course
(课程 ID、标题、部门名称、学分)我想编写一个触发器来自动更新获得可接受成绩的学生的
TotalCredits
(当教师更新学生所修课程的成绩时)。
我编写了这个触发器并执行了它:
CREATE TRIGGER [dbo].[credits_earned]
ON [dbo].[Takes]
AFTER UPDATE
AS
BEGIN
IF UPDATE(grade)
BEGIN
DECLARE @new_grade varchar(2)
SELECT @new_grade = I.grade
FROM inserted I
DECLARE @old_grade varchar(2)
SELECT @old_grade = T.grade
FROM Takes T
IF @new_grade<>'F' AND @new_grade IS NOT NULL
AND (@old_grade = 'F' OR @old_grade IS NULL)
BEGIN
UPDATE Student
SET tot_cred = tot_cred +
(SELECT credits
FROM Course C
WHERE C.course_id = (SELECT I.course_id
FROM inserted I))
WHERE Student.id = (SELECT I.id FROM inserted I)
END
END
END
命令成功完成。
但是当我执行一个程序来更新学生课程的成绩时(在 Takes 表中一年级为空),触发器对该学生的
TotalCredits
没有影响。
我将不胜感激你写的任何答案。
编写触发器逻辑时,它仍然是 SQL,因此仍然应该基于集合而不是基于过程(因为 SQL Server 针对基于集合的操作进行了优化)。
现在我认为以下方法有效。 (我正在假设什么唯一标识
Take
,以便将 Inserted
连接到 Deleted
(这就是检测更改的方式)。
然后我们需要预先聚合,因为无论成绩是否改变,您的聚合都会为所有
Takes
添加学分。
UPDATE s SET
tot_cred = tot_cred + c.Credits
FROM Student s
JOIN (
SELECT i.StudentId, SUM(c.Credits) Credits
FROM Inserted i
JOIN Deleted d ON d.StudentId = i.StudentId
AND d.CourseId = i.CourseId
AND d.SectionId = i.SectionId
AND d.Semester = i.Semester
AND d.Year = i.Year
JOIN Course c ON c.CourseId = i.CourseId
WHERE i.Grade <> 'F' AND i.Grade IS NOT NULL
AND (d.Grade = 'F' OR d.Grade IS NULL)
GROUP BY i.StudentId
) c ON c.Student = s.Id;