【发布时间】:2025-12-06 07:15:01
【问题描述】:
这个问题我已经坐了好几个小时了,我快要发疯了。我希望每个学生最多只能学习 45 个课程学分。在这一点上,它禁止我添加超过 45 个 CourseCredits。我应该如何重新排列函数 CheckCredits?
CREATE TABLE Student
(
studentID VARCHAR(5),
studentName VARCHAR(20),
studentAddress VARCHAR(20),
CONSTRAINT student_pk PRIMARY KEY(studentID)
)
CREATE TABLE Course
(
courseID VARCHAR(5),
courseCredits INT,
courseName VARCHAR(20),
CONSTRAINT course_pk PRIMARY KEY(courseID)
)
CREATE TABLE Studies
(
studentID VARCHAR(5),
courseID VARCHAR(5),
CONSTRAINT studies_pk PRIMARY KEY(studentID,courseID),
CONSTRAINT studies_fk_student FOREIGN KEY(studentID) REFERENCES Student(studentID) ON DELETE CASCADE,
CONSTRAINT studies_fk_course FOREIGN KEY(courseID) REFERENCES Course(courseID) ON DELETE CASCADE
)
CREATE TABLE HasStudied
(
studentID VARCHAR(5),
courseID VARCHAR(5),
grade VARCHAR(1),
CONSTRAINT has_studied_pk PRIMARY KEY(studentID,courseID),
CONSTRAINT has_studied_fk_student FOREIGN KEY(studentID) REFERENCES Student(studentID) ON DELETE CASCADE,
CONSTRAINT has_studied_fk_course FOREIGN KEY(courseID) REFERENCES Course(courseID) ON DELETE CASCADE
)
GO
CREATE FUNCTION CheckCredits()
RETURNS INT
AS
BEGIN
DECLARE @returnvalue INT
SELECT @returnvalue = (SELECT SUM(courseCredits) FROM Course c where c.courseID IN(
SELECT s.courseID FROM Studies s JOIN Student st ON s.studentID = st.studentID OR c.courseID = s.courseID))
RETURN @returnvalue
END;
GO
ALTER TABLE Studies
ADD CONSTRAINT chkCredits CHECK (dbo.CheckCredits() <= 45);
INSERT INTO Student VALUES('S1', 'Joe', 'Street')
INSERT INTO Student VALUES('S2', 'Joe', 'Street')
INSERT INTO Student VALUES('S3', 'Joe', 'Street')
INSERT INTO Student VALUES('S4', 'Joe', 'Street')
INSERT INTO Course VALUES('C1', 45, 'Biology')
INSERT INTO Course VALUES('C2', 15, 'History')
INSERT INTO Course VALUES('C3', 35, 'English')
INSERT INTO Course VALUES('C4', 20, 'Music')
INSERT INTO Studies VALUES('S1', 'C1')
INSERT INTO Studies VALUES('S2', 'C2')
INSERT INTO Studies VALUES('S3', 'C3')
【问题讨论】:
-
现在我不能将 S2 添加到 C2 或 S3 到 C3,因为 S1 研究有 45 分的 C1。所以它不认为学生是分开的。
-
检查功能正在应用于所有学生和课程。由于它返回 任何 学生注册的所有课程的
courseCredits的总和,因此它可能 > 45。使用trigger可能会做得更好,它只检查在适当的表中插入或更新的行。请注意,触发器每个 statement 触发一次,而不是 row。 -
感谢您的回复哈博。我很难理解触发器。有没有办法用函数做到这一点?
-
可以通过函数来完成,但它无法访问正在更新的特定行。因此,它必须检查每个学生的课程学分。首先编写一个查询,返回每个学生的总课程学分。然后你的支票变成
case when exists ( select Sum( courseCredits ) as totalCredits from ... group by studentId having totalCredits > 45 ) then 1 else 0 end。随着学生人数的增加,效率不是很高。和课程。以及多年的数据。 -
不要忘记 other 检查。如果课程更新为将
courseCredits设置为50,那么会发生什么?即使将一个从15更改为20也可能会导致学生违反您的规则,但直到Studies表中的某些不相关活动导致意外的约束违规时才会被检测到。
标签: sql-server tsql ddl stored-functions check-constraints