选课功能:“选课”是课程管理系统中的重要环节,选课将学生实体和课程实体有效连接起来。
选课功能的逻辑:
• 同一学生不能重复选同一门课
• 课程设置有人数上限,选课人数不能超过该上限
• 应提供课程还可供多少人选课的信息
• 如果课程设置有开始选课时间和(或)结束选课时间,在允
许的时间范围内方可选课
“选课”的业务逻辑表达的规则越多,就越值得用存储程序的眼光去看待“选课”,“选课”绝不仅仅是一个具体的“choose”表。以下定义一组存储程序来服务于课程管理。
存储程序实例
存储函数get_available_count
存储函数get_available_count,返回指定课程的可选课人数。
• 主表course表的Capacity字段值减去子表choose表中关联记录数
CREATE FUNCTION get_available_count(c_id CHAR(4))
RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
COMMENT '课程的可选课人数'
RETURN (
SELECT Capacity - (SELECT COUNT(*) FROM choose
WHERE choose.Course_id = course.Course_id)
FROM course WHERE course_id=c_id
);
调用get_available_count,查询包含可选课人数的课程列表
mysql> SELECT Course_id, Course_Name, Capacity,
-> get_available_count(Course_id) AS Available
-> FROM course
-> ORDER BY Available;
结果:
+-----------+----------------+----------+-----------+
| Course_id | Course_Name | Capacity | Available |
+-----------+----------------+----------+-----------+
| 1003 | 计算机基础 | 60 | 35 |
| 1004 | 数据库应用 | 60 | 40 |
| 1001 | 高等数学 | 60 | 40 |
| 1006 | 艺术概论 | 60 | 40 |
| 1010 | 大学英语(二) | 60 | 45 |
存储过程choose_course
存储过程choose_course,在数据库内记录学生和课程的关联
• 存储过程需要学号和课程号两个输入参数
• 存储过程应该用一个输出参数说明执行结果是成功还是失败
CREATE PROCEDURE choose_course(IN sid CHAR(12), IN cid CHAR(4),OUT status INT)
NOT DETERMINISTIC MODIFIES SQL DATA COMMENT '学生选课'
BEGIN
DECLARE begin_time, end_time DATETIME;
DECLARE dt_now DATETIME DEFAULT NOW();
// 定义局部变量
SELECT course.Begin_choose_time, course.End_choose_time
INTO begin_time, end_time FROM course where Course_id=cid;
// 返回结果集
-- 利用IF语句,用status在不同情况下返回不同的状态结果,向choose表插入记录
END
如果学生尚未选择某课程,并且课程容量允许,当前时间在选课时间范围内,就插入选课记录,否则报告相应的错误。
以下是详细的IF语句。
IF (SELECT COUNT(*) FROM choose WHERE Student_id=sid AND Course_id=cid) = 1 THEN
SET status = -1;
ELSEIF get_available_count(cid) = 0 THEN
SET status = -2;
ELSEIF begin_time IS NOT NULL AND dt_now < begin_time OR
end_time IS NOT NULL AND dt_now > end_time THEN
SET status = -3;
ELSE
INSERT INTO choose VALUES(NULL, sid, cid, dt_now, NULL);
SET status = 0;
END IF;
调用choose_course,完成选课业务操作
• 数据库中相关记录的情况不同,choose_course执行的结果可能不同。
SET @STATUS = 0;
CALL choose_course('201810201103', '1003', @status);
SELECT @STATUS;
解释:
@STATUS有四种状态,-1表示选课重复,-2表示课程容量已满,-3表示未在选课时间内,0表示选课成功
触发器choose_course_constraint
触发器choose_course_constraint,实现选课人数的约束
• 在choose表上创建BEFORE INSERT的触发器,如果新加记录的课程号所对应的课程可供选课人数已经为零,则报告错误。
CREATE TRIGGER choose_course_constraint
BEFORE INSERT
ON choose FOR EACH ROW
BEGIN
IF get_available_count(New.Course_id) = 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '课程选课人数已满';
END IF;
END
mysql> INSERT INTO choose VALUES(NULL,'201810201103','1003', NOW(), NULL);
ERROR 1644 (45000): 课程选课人数已满