MySQL设计学生选课系统(关系型数据库概论)

Posted 楊木木8023

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL设计学生选课系统(关系型数据库概论)相关的知识,希望对你有一定的参考价值。

/* 关系型数据库概论
1、-- DQL、DDL、DML、DCL
DQL数据查询语言: 用来查询表信息,select、from、where
DDL数据定义语言:用来创建数据库中的各种对象--表、视图,create table/view/index...
DML数据操纵语言:插入(insert),更新(update),删除(delete)
DCL数据控制语言:用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视,授权(grant),收回权限(revoke)

2、-- 数据库完整性规则
实体完整性:主键不能为空
参照完整性:外键R1 和关系R2中的主键相符合,那么外键的每个值必须在关系R2中主键的值中找到或者为空。(外键必须有与之相对应的主键存在)
用户自定义完整性:根据现实实际情况定义(如:年龄必须>0)

3、-- 数据库事务(ACID)
实现事务的关键是锁:锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。
原子性:原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性:一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
持久性:持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

4、-- 数据库死锁、活锁
活锁:如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待;T3也请求封锁R,当T1释放了R上的封锁之后系统首先批准了T3的请求,
      T2仍然等待;然后T4又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4的请求…T2有可能永远等待。
-- 避免活锁的简单方法是采用先来先服务的策略。
死锁:如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已封锁了R1,T2也只能等待T1释放R1上的锁。
      这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。
-- 预防死锁:(1)一次封锁法要求每个事务必须将所有要使用的数据全部加锁,否则就不能继续执行。
	     (2)顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实施封锁。
-- 接触死锁:(1)超时法;(2)等待图法

5、-- 索引
索引是特殊的查询表,数据库的搜索可以利用它加速对数据的检索。类似于书的目录,不需要查询整本书内容就可以找到想要的数据。
索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据的增加删除速度,同时也增加了数据库的占用空间。

6、-- 视图、游标
-- 视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,视图通常是有一个表或者多个表的行或列的子集。对视图的修改会影响基本表。 
-- 游标是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。
-- 视图其实就是一条查询sql语句,用于显示一个或多个表或其他视图中的相关数据。 表就是关系数据库中实际存储数据用的。

7、-- 触发器
-- 触发器可通过数据库中的相关表实现级联更改;通过级联引用完整性约束可以更有效地执行这些更改。
*/


/*
设计学生选课系统:
包括学院信息表、学生信息表、教师信息表、课程表、选课记录表。
学院信息表属性:id(int 主键)、名称(varchar)、网站(varchar)
学生信息表属性:id(int 主键)、姓名(varchar)、性别(int)、生日(date)、所属学院(int),外键约束为所属学院(col_id)
教师信息表属性:id(int 主键)、姓名(varchar)、职称(varchar)、所属学院(int),外键约束为所属学院(col_id)
课程表属性:id(int 主键)、课程名(varchar)、学分(int)、授课教师(int),外键约束为授课教师(tea_id)
选课记录表属性:id(int 主键)、所选学生(int)、选课时间(datetime)、考试成绩(decimal),外键约束为学生(stu_id)、课程(cou_id)
*/

-- 创建数据库Student_Course_System 默认字符集 utf-8
CREATE DATABASE Student_Course_System DEFAULT CHARSET utf8;
-- 切换数据库
USE Student_Course_System

-- 创建学院信息表
CREATE TABLE tb_college(
	col_id INT NOT NULL PRIMARY KEY COMMENT '编号',
	col_name VARCHAR(50) NOT NULL COMMENT '名称',
	website VARCHAR(1024) COMMENT '官网'
);

-- 创建学生信息表
-- alter table tb_student change column stu_sex stu_sex int;
CREATE TABLE tb_student(
	stu_id INT PRIMARY KEY NOT NULL COMMENT '学号',
	stu_name VARCHAR(20) NOT NULL COMMENT '姓名',
	stu_sex BIT DEFAULT 1 COMMENT '性别',
	stu_birth DATE COMMENT '生日',
	col_id INT NOT NULL COMMENT '所属学院',
	FOREIGN KEY (col_id) REFERENCES tb_college (col_id)
);

-- 创建教师信息表
CREATE TABLE tb_teacher(
	tea_id INT PRIMARY KEY NOT NULL COMMENT '工号',
	tea_name VARCHAR(50) NOT NULL COMMENT '姓名',
	tea_title VARCHAR(10) DEFAULT '助教' COMMENT '职称',
	col_id INT NOT NULL COMMENT '所属学院',
	FOREIGN KEY (col_id) REFERENCES tb_college (col_id)
);

-- 创建课程信息表
CREATE TABLE tb_course(
	cou_id INT PRIMARY KEY NOT NULL COMMENT '编号',
	cou_name VARCHAR(50) NOT NULL COMMENT '名称',
	cou_credit INT NOT NULL COMMENT '学分',
	tea_id INT NOT NULL COMMENT '授课老师',
	FOREIGN KEY (tea_id) REFERENCES tb_teacher (tea_id)
);

-- 创建选课信息表
-- DROP TABLE tb_score;
CREATE TABLE tb_score(
	sc_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '选课记录编号',
	stu_id INT NOT NULL COMMENT '选课学生',
	cou_id INT NOT NULL COMMENT '所选课程',
	sc_date DATETIME COMMENT '选课时间',
	sc_mark DECIMAL(4, 1) COMMENT '考试成绩',
	FOREIGN KEY (stu_id) REFERENCES tb_student (stu_id),
	FOREIGN KEY (cou_id) REFERENCES tb_course (cou_id)
);

-- 添加唯一性约束(一个学生选某个课程只能选一次)
ALTER TABLE tb_score ADD CONSTRAINT uni_score_stuid_couid UNIQUE(stu_id, cou_id);

-- 向学院信息表中添加信息
INSERT INTO tb_college VALUES
	('1001', '计算机科学与工程学院', 'https://www.abc.com'),
	('1002', '外国语言文学学院', 'https://www.def.com'),
	('1003', '国际经济与贸易学院', 'https://www.ghj.com');

-- 向学生信息表中添加信息
INSERT INTO tb_student VALUES
	(201001001, '张山', 1, '1998-02-20', 1001),
	(201001002, '张柳柳', 0, '1998-09-21', 1001),
	(201001003, '李立群', 1, '1999-11-12', 1001),
	(201001004, '王建军', 1, '1997-09-13', 1001),
	(201001005, '刘丽芳', 0, '1998-07-04', 1001),
	(201002001, '杨飞飞', 0, '1998-09-20', 1002),
	(201002002, '黄立功', 1, '1997-10-12', 1002),
	(201002003, '陈一新', 1, '1999-05-19', 1002),
	(201003001, '王建军', 1, '1999-09-13', 1003),
	(201003002, '刘丽芳', 0, '1998-06-09', 1003);

-- 向教师信息表中添加信息
INSERT INTO tb_teacher VALUES
	(100110, '王建国', '教授', 1001),
	(100121, '李剑锋', '副教授', 1001),
	(100219, '陈恺恺', '讲师', 1002),
	(100204, '黄奕芳', '教授', 1002),
	(100321, '郭建', '讲师', 1003);

-- 向课程信息表添加信息
-- update tb_course set cou_id=1002803 where cou_name='英语语法概论';
INSERT INTO tb_course VALUES
	(1001901, '数据库系统概论', 2, 100110),
	(1001902, '计算机网络', 3, 100121),
	(1001903, 'C程序设计', 2, 100110),
	(1002801, '标准日语', 3, 100219),
	(1002802, '日本文化发展史', 1, 100219),
	(1002803, '英语语法概论', 1, 100204),
	(1003701, '会计学概论', 1, 100321),
	(1003702, '经济学基础概论', 2, 100321);

-- 向选课信息表添加信息
INSERT INTO tb_score VALUES
	(1, 201001001, 1001901, NOW(), 95),
	(2, 201001001, 1001902, NOW(), 89),
	(3, 201001002, 1001901, NOW(), 91),
	(4, 201001003, 1001902, NOW(), 78),
	(5, 201001003, 1001903, NOW(), 87),
	(6, 201001004, 1001901, NOW(), 88),
	(7, 201002001, 1002801, NOW(), 95),
	(8, 201002002, 1002802, NOW(), 65),
	(9, 201002003, 1002803, NOW(), 82),
	(10, 201003001, 1003701, NOW(), 97),
	(11, 201003001, 1003702, NOW(), 87),
	(12, 201003002, 1003701, NOW(), 88),
	(13, 201003002, 1003702, NOW(), 83);

-- 查询学生信息表的所有信息
SELECT * FROM tb_student;
SELECT * FROM tb_teacher;
-- 查询显示学生信息表的学号和姓名
SELECT stu_id, stu_name FROM tb_student;
-- 别名
SELECT stu_id AS '学号', stu_name AS '姓名' FROM tb_student;
-- 将性别1显示为男,性别0显示为女
SELECT stu_name AS '姓名', CASE stu_sex WHEN 1 THEN '男' ELSE '女' END AS '性别' FROM tb_student;
-- 查询性别为女的学生的姓名和出生日期
SELECT stu_name, stu_birth FROM tb_student WHERE stu_sex=0;
-- 查询出生在1999年的学生的姓名和出生日期
SELECT stu_name, stu_birth FROM tb_student WHERE stu_birth BETWEEN '1999-01-01' AND '1999-12-31';

-- 模糊查询
-- 查询张姓学生的姓名和学号
SELECT stu_name, stu_id FROM tb_student WHERE stu_name LIKE '张%';
-- 查询张姓且名字为两字的学生的姓名和学号
SELECT stu_name, stu_id FROM tb_student WHERE stu_name LIKE '张_';
-- 查询姓名中包含 立 或者 飞 的学生的姓名和学号
SELECT stu_name, stu_id FROM tb_student WHERE stu_name LIKE '%立%' OR stu_name LIKE '%飞%';
-- 结果去重
SELECT DISTINCT sc_date FROM tb_score;
-- 按出生日期降序排序
SELECT stu_name, stu_birth FROM tb_student WHERE stu_sex=1 ORDER BY stu_birth DESC;  -- asc
-- 查询男学生的姓名和年龄并按照出生日期降序排序
SELECT stu_name AS '姓名', YEAR(NOW()) - YEAR(stu_birth) AS '年龄' FROM tb_student WHERE stu_sex=1 ORDER BY stu_birth DESC;

-- 聚合函数,max\\min\\count\\sum\\avg..... 
SELECT MIN(stu_birth) FROM tb_student;
SELECT COUNT(stu_id) FROM tb_student;
SELECT COUNT(stu_id), stu_sex FROM tb_student WHERE stu_sex=1;
SELECT COUNT(stu_id), stu_sex FROM tb_student GROUP BY stu_sex;
SELECT AVG(sc_mark), cou_id FROM tb_score WHERE cou_id=1001901;
SELECT AVG(sc_mark), stu_id FROM tb_score WHERE stu_id=201001001;
SELECT stu_id, AVG(sc_mark) FROM tb_score GROUP BY stu_id;
-- 分组之前的筛选可以使用where写在group by的前面,但是筛选在分组之后的需要使用having
SELECT stu_id, AVG(sc_mark) FROM tb_score GROUP BY stu_id HAVING AVG(sc_mark)>=90;

-- 嵌套查询(子查询)
SELECT stu_name, stu_birth FROM tb_student WHERE stu_birth = (SELECT MIN(stu_birth) FROM tb_student);
-- 查询选了两门及以上课程的学生姓名
SELECT stu_name FROM tb_student WHERE stu_id IN (SELECT stu_id FROM tb_score GROUP BY stu_id HAVING COUNT(*) >= 2);
-- 连接查询(查询学生姓名、课程名称以及考试成绩)
SELECT stu_name, cou_name, sc_mark FROM tb_student t1, tb_course t2, tb_score t3 WHERE t1.stu_id=t3.stu_id AND t2.cou_id=t3.cou_id; 
-- 查询选课学生的姓名和平均成绩
SELECT stu_name, avg_mark FROM tb_student t1, (SELECT stu_id , AVG(sc_mark) AS avg_mark FROM tb_score GROUP BY stu_id) t2 
WHERE t1.stu_id=t2.stu_id;

-- 索引
-- 没建立索引之前,用explain查看详细的查询过程,可以发现查询type是all,查询的行数是全部行
-- 负向条件,如<>,模糊查询,不可以使用索引
EXPLAIN SELECT stu_name FROM tb_student WHERE stu_name='陈一新';
-- 索引,可以加快查询速度,相当于加上目录,也就是以空间换时间,但是索引会拖慢增删的速度
-- 索引应该建在最常用的查询列上
-- 给学生表的学生姓名建立索引
CREATE INDEX idx_stu_name ON tb_student (stu_name);
DROP INDEX idx_stu_name ON tb_student;
-- 建立索引之后,用explain查看详细的查询过程,可以发现查询type是ref,查询的行数是匹配行
EXPLAIN SELECT stu_name FROM tb_student WHERE stu_name='陈一新';

-- 视图,相当于查询的快照,对于下面例子,相当于把查询记录下来,下次可以直接通过视图查看
-- 视图还可以限制用户权限,仅仅给与用户给定的信息查询权限,表的其他信息无权限查看
CREATE VIEW vw_tb_student AS
SELECT stu_id, stu_name, stu_birth FROM tb_student WHERE stu_sex=1;
-- 通过视图查看查询的信息
SELECT * FROM vw_tb_student;
-- 删除视图
DROP VIEW vw_tb_student;

-- DCL: 创建新用户,用户名aaaa,连接密码123456
CREATE USER 'aaaa'@'%' IDENTIFIED BY '23456';
-- 授予用户针对数据库Student_Course_System的所有权限
GRANT ALL PRIVILEGES ON Student_Course_System.* TO 'aaaa'@'%';
-- 召回权限,召回用户的插入和删除权限
REVOKE INSERT, DELETE ON Student_Course_System.* FROM 'aaaa'@'%';

以上是关于MySQL设计学生选课系统(关系型数据库概论)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL设计学生选课系统(关系型数据库概论)

XK关系型学生选课数据库,关系如下:

数据库系统概论大作业试验

数据库系统概论大作业试验

数据库系统概论大作业试验

选课系统设计