1.准备

student表结构:

字段名称 数据类型 是否允许空值 约束 说明
SNo char(8) × 主键 学号
SName varchar(15) × 唯一值 姓名
SSex char(1) × 检查约束 性别(男或女)
Sdept varchar(20) √ 默认值(软件工程) 所在系
SBir datetime √ 出生日期
Scredits int √ 总学分
create table student(
	SNo char(8) primary key,
	SName varchar(15) not null unique,
	SSex enum('男','女') not null,
	Sdept varchar(20) default '软件工程' ,
	SBir datetime,
	Scredits int
);

course表结构:

字段名称 数据类型 是否允许空值 约束 说明
CNo char(5) × 主键 课程编号
CName varchar(30) × 唯一值 课程名称
CPno char(5) √ 外码 先修课程
CTime decimal(3,0) √ 总学时
CCredit int √ 默认值4 学分
CTerm char(1) × 学期
create table course(
	CNo char(5) primary key,
	CName varchar(30) not null ,
	CPno char(5),
	CTime decimal(3,0),
	CCredit int default 4,
	CTerm char(1) not null,
	foreign key(CPno) references `course`(CNo)
);

SC表结构:

字段名称 数据类型 是否允许空值 约束 说明
SNo char(8) × 外码(联合主键) 学号
CNo char(5) × 外码(联合主键) 课程编号
Score decimal(3,1) √ 0~100 成绩
create table sc(
	SNo char(8) not null,
	CNo char(5) not null,
	Score decimal(3,1) ,
	primary key(SNo,CNo),
	foreign key(SNo) references `student`(SNo),
	foreign key(CNo) references `course`(CNo)
);

# 给分数创建触发器
DELIMITER $
create trigger scorecheck before insert on SC for each row
begin
if new.Score<0 or new.Score>100 then set new.Score=-1;end if;
end $
DELIMITER ;

2.增删改

# 插入数据
insert into student values('00000001','张三','男','软件工程','1800-05-19',11);
insert into fstu select * from student where SSex='女';

# 删除记录
delete * from sc;
delete from student where SNo='00000001';

# 修改
update student set SSex='女',Scredits=10 WHERE SName='刘宏';
update sc set Score=Score*0.9 where cno = (select cno from course where cname="c语言");

3.查询

1. 单表查询

简单查询

select * from student where Sname in ("张三","李四");			# in 散点查询
select sname from student where sno like "%01";					# like 模糊查询
select sno from student where scredits between 6 and 11;		# between...and...范围查找
select sname from student where scredits>6 and scredits<=11;

# 聚集函数
count()、substring()、max()、min()、avg()、sum()

分组查询

# 统计各个班级的的学生人数,按照学生人数降序显示
select substring(sno,1,6)班级,count(substring(sno,1,6))人数
from student 
group by substring(sno,1,6)
order by count(substring(sno,1,6)) desc;

# 查询不同学时的课程数大于等于3门课程的学时及门数
select ctime"课时",count(*)"数目"
from course
group by Ctime
having count(cno)>=3;

# 找出每门课程分数相同的人数
select cno"课程号",score"分数",count(*)"数目"
from sc
group by cno,score
having count(cno)>=2;

# 查找岁数相同的同学的数目
select year(Sbir)`出生年`,count(*)数目
from student 
group by year(Sbir);

# 按照不同性别,不同出生年份分组统计相应人数
select ssex`性别`,year(Sbir)`出生年`,count(*)数目
from student 
group by ssex,year(Sbir);

Limit限制结果

# 数据分成3页显示,每页5条记录。现查看第2页数据信息
select * from student limit 5,5;

# 查看5-10条学生信息
select * from student limit 6 offset 4;

2.多表查询

自然连接查询(=)

# 查询成绩在70至85之间(含边界值)的“男”同学的学号、姓名、课程名及成绩,并按成绩降序排列

select student.sno"学号",sname"姓名",cname"课程名",score"成绩"
from student,course,sc
where sc.cno=course.cno and
	student.sno=sc.sno and
	sc.score between 70 and 85 and
	student.ssex="男"
order by score desc;

select student.sno"学号",sname"姓名",cname"课程名",score"成绩"
from student
natural join course natural join sc
where ssex="男" and score between 70 and 85
order by score desc;

内连接查询(inner JOIN…ON)

# 查询成绩为空的"男"同学的学号 姓名 课程名 成绩

select student.sno"学号",sname"姓名",cname"课程名",score"成绩"
from student
inner join sc
on student.sno=sc.sno and ssex="男"
inner join course
on course.cno=sc.cno and score is null;

(左)外连接查询(left JOIN…ON)

select s.sno"学号",sname"姓名",cname"课程名",score"成绩"
from student as s
left join sc
on s.sno=sc.sno
left join course as c
on c.cno=sc.cno
order by s.sno;

嵌套查询

# 查询和“数据结构”课程在同一学期开设并且超过36学时的课程名

select cname
from course
where cterm=(
	select cterm
	from course
	where cname="数据结构"
) and ctime>36;

基于派生表的查询

# 查询“00009”号课程成绩最高分的同学的学号、姓名

select sno"学号",sname"姓名"
from student,(select sno as m_sno,max(score) as m_score
		from sc
		where score=(
			select max(score)
			from sc
			where cno="00009")) as max_score
where student.sno=max_score.m_sno;

4.其他

1.视图

# 显示软件工程 课程号为“00004”的分数加5
create view v_addscore(学号,姓名,课程号,课程,分数)
	as
	select s.sno,sname,c.cno,cname,score+5
	from student s,course c,sc
	where s.sno=sc.sno and c.cno=sc.cno and s.sdept="软件工程" and sc.cno="00004";

如果视图包含下述结构中的任何一种,那么它就是不可更新的:
(1)聚合函数;
(2)DISTINCT关键字;
(3)GROUP BY子句;
(4)ORDER BY子句;
(5)HAVING子句;
(6)UNION运算符;
(7)位于选择列表中的子查询;
(8)FROM子句中包含多个表;
(9)SELECT语句中引用了不可更新视图;
(10)WHERE子句中的子查询,引用FROM子句中的表;
(11)ALGORITHM 选项指定为TEMPTABLE(使用临时表总会使视图成为不可更新的)

2.存储过程

delimiter更改SQL语句结束符
不带参数的

# 创建一个存储过程,返回软件专业本班大于20岁的学生学号,姓名,性别
delimiter $
create procedure ageup20()
begin
select sno"学号",sname"姓名",ssex"性别",year(curdate())-year(sbir)"年龄"
from student
where sdept="软件工程" and (year(curdate())-year(sbir))>20;
end $
delimiter ;

call ageup20();		# 调用

带参数的

# 创建一个存储过程,实现查询某门课程成绩在60~90之间的男学生名单
delimiter $
create procedure stu_score(in s_cname varchar(20))
begin
if s_cname!=null and s_cname!="" then
select sname
from student s,course c,sc
where s.sno=sc.sno and c.cno=sc.cno
      and s.ssex="男" and c.cname=s_cname
      and score>=60 and score<=90;
end if;
end $
delimiter ;

delimiter $
create procedure stu_score1 (in s_cname varchar(20))
begin
if s_cname!=null and s_cname!="" then
select sname
from student
where sno in (
    select sno
    from sc
    where cno in (
        select cno
        from course
        where cname=s_cname
) and score>=60 and score<=90
) and ssex="男";
end if;
end $
delimiter ;

call stu_score("数据库系统");

带输入、输出参数的存储过程

# 创建一个存储过程,实现计算全体学生某门功课的平均成绩的功能
delimiter $
create procedure s_avg(in c_name varchar(25),out c_no varchar(20),out c_avg decimal(5,2))
begin
if c_name!=null or c_name!="" then
select cno,avg(score) into c_no,c_avg
from sc
where cno=(
    select cno
    from course
    where cname=c_name
)
group by cno;
end if;
end$
delimiter ;

call s_avg("c语言",@no,@res);

select @no,@res;

3.存储函数

# 创建一个存储函数,返回sc表中某门课的数目,有结果返回实际选课数,无结果显示“无人选此课”

delimiter $
create function c_count(c_name varchar(20))
returns varchar(20)
begin
declare num int;
set num=(select count(*)
	from sc
	where cno=(select cno from course where cname=c_name));
if(num!=0) then
     return(concat(num,""));
else
    return("无人选此课");
end if;
end$
delimiter ;

select c_count("c语言");

5.数据库的备份与还原

  • 使用mysqldump备份chapter08数据库 mysqldump -uroot -proot chapter08>d:\文件\数据库\备份\chapter08.sql
  • 备份多个数据库 mysqldump -uroot -proot --database chapter08 sm1>d:\文件\数据库\备份\two.sql
  • 还原chapter08数据库 mysql -u root -p root chaptr08<d:\文件\数据库\备份\chapter08.sql
  • 还原多个数据库 mysql -u root -proot <d:\文件\数据库\备份\two.sql

6.用户管理(这里是旧版[5.0],新版本[8.0]将创建与授权分开)

改变数据库 use mysql;

  • 使用SELECT语句查看mysql.user表内容
    select * from mysql.user \G;

  • 使用CREATE USER语句创建用户(创建用户aaa 可远程登陆 密码为:123456789)
    create user "aaa"@"%" identified by "123456789";

  • 使用GRANT语句创建用户(创建用户aaa 所有权限 只能本地登陆 密码为:123456789)
    grant all privileges on *.* to aaa@localhost identified by '123456789' with grant option;

  • 使用INSERT语句创建用户(创建用户ai 本地连接 密码:123456789)
    insert into mysql.user(Host,User,Password) values("localhost","ai",password("123456789"));
    错误的原因是mysql默认配置严格模式,该模式禁止通过insert的方式直接修改mysql库中的user表进行添加新用户。
    解决方法是修改my.ini(Windows系统)或my.conf(Linux系统)配置文件
    sql-mode=" STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
    修改为:sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" =>重启mysql服务

  • 删除普通用户(删除用户'ai'@'localhost)
    drop user 'ai'@'localhost';

  • 修改用户密码(修改’aaa’@’%’密码为987654321)
    update mysql.user set password = password('987654321') where user = 'ahb' and host = '%';
    flush privileges; 刷新MySQL系统权限相关表,否则会拒绝访问

  • 权限管理..........