如何将 AFTER UPDATE TRIGGER 写入包含这些详细信息的列?

问题描述 投票:0回答:1

在我的

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-server t-sql triggers sql-update sql-server-2019
1个回答
0
投票

编写触发器逻辑时,它仍然是 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;
© www.soinside.com 2019 - 2024. All rights reserved.