第七章 数据库-SQL语言
一、SQL语言
1、主要操作
- 数据表操作
- 创建表
- 删除表
- 数据操作
- 增加数据
- 删除数据
- 修改数据
- 查询数据(重点)
2、SQL语言的编写和运行

- 选择表名
- 选择 新建查询

- 编写SQL语句
- 运行 查看结果
3、数据表操作
3.1、创建表
1 create table 表名( 2 字段名 类型 约束, 3 字段名 类型 约束 4 ... 5 )
例:创建学生表,字段要求如下:
姓名(长度为10)
1 create table students( name varchar(10) )
例:创建学生表,字段要求如下:
姓名(长度为10),年龄
1 create table students( 2 name varchar(10), 3 age int unsigned 4 )
例:创建学生表,字段要求如下:
姓名(长度为10),年龄,身高(保留小数点2位)
1 create table students( 2 id int unsigned primary key auto_increment, 3 name varchar(20), 4 age int unsigned, 5 height decimal(5,2) 6 )
3.2、删除表
1 格式一:drop table 表名 2 格式二:drop table if exists 表名
3 例:删除学生表 4 drop table students 5 或 6 drop table if exists students
4、数据操作-增删改查
4.1、简单查询
1 select * from 表名 2 例:查询所有学生数据 3 select * from students
4.2、添加数据
4.2.1、添加一行数据
格式一:所有字段设置值,值的顺序与表中字段的顺序对应
- 说明:主键列是自动增长,插入时需要占位,通常使用0或者 default 或者 null 来占位,插入 成功后以实际数据为准
1 insert into 表名 values(...) 2 例:插入一个学生,设置所有字段的信息 3 insert into students values(0,'亚瑟',22,177.56)
格式二:部分字段设置值,值的顺序与给出的字段顺序对应
1 insert into 表名(字段1,...) values(值1,...) 2 例:插入一个学生,只设置姓名 3 insert into students(name) values('老夫子')
4.2.2、添加多行数据
方式一:写多条insert语句,语句之间用英文分号隔开
1 insert into students(name) values('老夫子2');
2 insert into students(name) values('老夫子3');
3 insert into students values(0,'亚瑟2',23,167.56)
方式二:写一条insert语句,设置多条数据,数据之间用英文逗号隔开
1 格式一:insert into 表名 values(...),(...)... 2 例:插入多个学生,设置所有字段的信息 3 insert into students values(0,'亚瑟3',23,167.56),(0,'亚瑟4',23,167.56)
4 格式二:insert into 表名(列1,...) values(值1,...),(值1,...)... 5 例:插入多个学生,只设置姓名 6 insert into students(name) values('老夫子5'),('老夫子6')
4.2.3、修改
1 update 表名 set 列1=值1,列2=值2... where 条件
2 例:修改id为5的学生数据,姓名改为 狄仁杰,年龄改为 20
3 update students set name='狄仁杰',age=20 where id=5
4.2.4、删除
格式一:delete from 表名 where 条件
1 例:删除id为6的学生数据
2 delete from students where id=6
逻辑删除:对于重要的数据,不能轻易执行 delete 语句进行删除。因为一旦删除,数据无法恢 复,这时可以进行逻辑删除。
- 给表添加字段,代表数据是否删除,一般起名 isdelete,0代表未删除,1代表删除,默认值为0
- 当要删除某条数据时,只需要设置这条数据的 isdelete 字段为1
- 以后在查询数据时,只查询出 isdelete 为0的数据
例:
1、给学生表添加字段(isdelete),默认值为0, 如果表中已经有数据,需要把所有数据的isdelete字段更新为0
update students set isdelete=0
2、删除id为1的学生
update students set isdelete=1 where id=1
3、查询未删除的数据 10
select * from students where isdelete=0
格式二:truncate table 表名(删除表的所有数据,保留表结构)
1 例:删除学生表的所有数据
2 truncate table students
格式三:drop table 表名(删除表,所有数据和表结构都删掉)
1 例:删除学生表
2 drop table students
Truncate、Delete、Drop 的区别
- Delete 删除数据时,即使删除所有数据,其中的自增长字段不会从1开始
- Truncate 删除数据时,其中的自增长字段恢复从1开始
- Drop 是删除表,所有数据和表结构都删掉
总结
- 在速度上,drop > truncate > delete
- 如果想删除部分数据用 delete,注意带上 where 子句
- 如果想删除表,用 drop
- 如果想保留表而将所有数据删除,自增长字段恢复从1开始,用 truncate
5、数据操作-查询
5.1、数据准备
5.1.1、创建数据表
1 drop table if exists students; 2 create table students ( 3 studentNo varchar(10) primary key, 4 name varchar(10), 5 sex varchar(1), 6 hometown varchar(20), 7 age tinyint(4), 8 class varchar(10), 9 card varchar(20) 10 );
5.1.2、插入数据
1 insert into students values 2 ('001', '王昭君', '女', '北京', '20', '1班', '340322199001247654'), 3 ('002', '诸葛亮', '男', '上海', '18', '2班', '340322199002242354'), 4 ('003', '张飞', '男', '南京', '24', '3班', '340322199003247654'), 5 ('004', '白起', '男', '安徽', '22', '4班', '340322199005247654'), 6 ('005', '大乔', '女', '天津', '19', '3班', '340322199004247654'), 7 ('006', '孙尚香', '女', '河北', '18', '1班', '340322199006247654'), 8 ('007', '百里玄策', '男', '山西', '20', '2班', '340322199007247654'), 9 ('008', '小乔', '女', '河南', '15', '3班', null), 10 ('009', '百里守约', '男', '湖南', '21', '1班', ''), 11 ('010', '妲己', '女', '广东', '26', '2班', '340322199607247654'), 12 ('011', '李白', '男', '北京', '30', '4班', '340322199005267754'), 13 ('012', '孙膑', '男', '新疆', '26', '3班', '340322199000297655');
5.2、查询基本语法
5.2.1、查询所有字段
1 语法: 2 select * from 表名
3 例:查询所有学生的所有字段 4 select * from students
5.2.2、查询部分字段
1 语法: 2 select 字段1,字段2,... from 表名
3 例:查询所有学生的姓名、性别、年龄 4 select name,sex,age from students
5.2.3、起别名
1 给表起别名,在多表查询中经常使用 2 语法: 3 select 别名.字段1,别名.字段2,... from 表名 as 别名
4 例:给学生表起别名 5 select s.name,s.sex,s.age from students as s;
1 给字段起别名,这个别名出现在结果集中 2 语法: 3 select 字段1 as 别名1,字段2 as 别名2,... from 表名
4 例:查询所有学生的姓名、性别、年龄,结果中的字段名显示为中文 5 select name as 姓名,sex as 性别,age as 年龄 from students;
5.2.4、去重
1 语法: 2 select distinct 字段1,... from 表名
3 例:查询所有学生的性别,不显示重复的数据 4 select distinct sex from students;
6、条件查询
6.1、语法格式
使用where子句对表中的数据筛选,符合条件的数据会出现在结果集中
6.1.1、语法
1 select 字段1,字段2... from 表名 where 条件;
2 -- eg:
3 select * from students where id=1;
where后面支持多种运算符,进行条件的处理
- 比较运算符
- 逻辑运算
- 模糊查询
- 范围查询
- 空判断
6.1.2、比较运算符
- 等于: =
- 大于: >
- 大于等于: >=
- 小于: <
- 小于等于: <=
- 不等于: != 或 <>
1 例1:查询小乔的年龄 2 select age from students where name='小乔'
3 例2:查询20岁以下的学生 4 select * from students where age<20
5 例3:查询家乡不在北京的学生 6 select * from students where hometown!='北京'
练习:1、查询学号是'007'的学生的身份证号2、查询'1班'以外的学生信息3、查询年龄大于20的学生的姓名和性别
6.1.3、逻辑运算符
- and
- or
- not
1 例1:查询年龄小于20的女同学
2 select * from students where age<20 and sex='女'
3 例2:查询女学生或'1班'的学生
4 select * from students where sex='女' or class='1班'
5 例3:查询非天津的学生
6 select * from students where not hometown='天津'
练习:
1、查询河南或河北的学生
2、查询'1班'的'上海'的学生
3、查询非20岁的学生
6.1.4、模糊查询
- like
- %表示任意多个任意字符
- _表示一个任意字符
1 例1:查询姓孙的学生 2 select * from students where name like '孙%'
3 例2:查询姓孙且名字是一个字的学生 4 select * from students where name like '孙_'
5 例3:查询姓名以乔结尾的学生 6 select * from students where name like '%乔'
7 例4:查询姓名含白的学生 8 select * from students where name like '%白%'
练习:
1、查询姓名为两个字的学生
2、查询姓百且年龄大于20的学生
3、查询学号以1结尾的学生
6.1.5、范围查询
-
in表示在一个非连续的范围内
1 例1:查询家乡是北京或上海或广东的学生
2 select * from students where hometown in('北京','上海','广东')
-
between ... and ...表示在一个连续的范围内
1 例2:查询年龄为18至20的学生
2 select * from students where age between 18 and 20
练习:
1、查询年龄在18或19或22的女生
2、查询年龄在20到25以外的学生
6.1.6、空判断
-
注意:null与' '是不同的
-
判空is null
1 例1:查询没有填写身份证的学生 2 select * from students where card is null
- 判非空is not null
1 例2:查询填写了身份证的学生 2 select * from students where card is not null
7、排序
为了方便查看数据,可以对数据进行排序
7.1、排序
7.1.1、语法
1 select * from 表名 2 order by 列1 asc|desc,列2 asc|desc,...
- 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
- 默认按照列值从小到大排列
- asc从小到大排列,即升序
- desc从大到小排序,即降序
7.1.2、示例
1 例1:查询所有学生信息,按年龄从小到大排序
2 select * from students order by age
3 例2:查询所有学生信息,按年龄从大到小排序,年龄相同时,再按学号从小到大排序
4 select * from students order by age desc,studentNo
练习:
1、查询所有学生信息,按班级从小到大排序,班级相同时,再按学号再按学号从小到大排序
8、聚合函数
8.1、聚合函数
-
使用聚合函数方便进行数据统计
-
聚合函数不能在 where 中使用
常用聚合函数
-
count(): 查询总记录数
-
max(): 查询最大值
-
min(): 查询最小值
-
sum(): 求和
-
avg(): 求平均值
8.1.1、查询总记录数
count(*)表示计算总行数,括号中也可以使用字段名
1 示例:查询学生总数
2 select count(*) from students;
8.1.2、查询最大值
max(列)表示求此列的最大值
1 示例:查询女生的最大年龄
2 select max(age) from students where sex='女';
8.1.3、查询最小值
min(列)表示求此列的最小值
1 示例:查询1班的最小年龄
2 select min(age) from students;
8.1.4、求和
sum(列)表示求此列的和
1 示例:查询北京学生的年龄总和
2 select sum(age) from students where hometown='北京';
8.1.5、求平均值
avg(列)表示求此列的平均值
1 示例:查询女生的平均年龄
2 select avg(age) from students where sex='女'
8.1.6、练习
1、查询所有学生的最大年龄、最小年龄、平均年龄
2、一班共有多少个学生
3、查询3班年龄小于18岁的同学有几个
9、分组
9.1、分组
-
按照字段分组,此字段相同的数据会被放到一个组中
-
分组的目的是对每一组的数据进行统计(使用聚合函数)
9.1.1、语法
select 字段1,字段2,聚合... from 表名 group by 字段1,字段2...
1 例1:查询各种性别的人数
2 select sex,count(*) from students group by sex
3 例2:查询每个班级中各种性别的人数
4 select class,sex,count(*) from students group by class,sex
练习
1、查询各个班级学生的平均年龄、最大年龄、最小年龄
9.2、分组后的数据筛选
9.2.1、语法
1 select 字段1,字段2,聚合... from 表名
2 group by 字段1,字段2,字段3...
3 having 字段1,...聚合...
- having后面的条件运算符与where的相同
1 例1:查询男生总人数
2 方案一
3 select count(*) from students where sex='男'
4 -----------------------------------
5 方案二:
6 select sex,count(*) from students group by sex having sex='男'
练习
1、查询1班除外其他班级学生的平均年龄、最大年龄、最小年龄
9.2.2、对比where与having
-
where 是对 from 后面指定的表进行数据筛选,属于对原始数据的筛选
-
having 是对 group by 的结果进行筛选
-
having 后面的条件中可以用聚合函数,where 后面不可以
10、分页
10.1、获取部分行
当数据量过大时,在一页中查看数据是一件非常麻烦的事情
10.1.1、语法
1select * from 表名 limit start,count
- 从start开始,获取count条数据
- start索引从0开始
1 例1:查询前3行学生信息
2 select * from students limit 0,3
练习:
1、查询第4到第6行学生信息
10.2、分页
limit典型的应用场景就是实现分页查询
1 已知:每页显示m条数据,求:显示第n页的数据
2 select * from students limit (n-1)*m,m
练习:1、每页显示5条数据,显示每一页的数据
扩展:已知总记录数和每页显示条数,求总页数
11、链接查询
11.1、链接查询
11.1.1、常用的链接方式
-
内链接:查询的结果为两个表匹配到的数据

-
左连接:查询的结果为两个表匹配到的数据加左表特有的数据,对于右表中不存在的数据使用 null 填充

-
右连接:查询的结果为两个表匹配到的数据加右表特有的数据,对于左表中不存在的数据使用 null 填充

11.2、准备数据
1 drop table if exists courses;
2 create table courses (
3 courseNo int(10) unsigned primary key auto_increment,
4 name varchar(10)
5 );
6
7 insert into courses values
8 ('1', '数据库'),
9 ('2', 'qtp'),
10 ('3', 'linux'),
11 ('4', '系统测试'),
12 ('5', '单元测试'),
13 ('6', '测试过程');
14
15 drop table if exists scores;
16 create table scores (
17 id int(10) unsigned primary key auto_increment,
18 courseNo int(10),
19 studentno varchar(10),
20 score tinyint(4)
21 );
22
23 insert into scores values
24 ('1', '1', '001', '90'),
25 ('2', '1', '002', '75'),
26 ('3', '2', '002', '98'),
27 ('4', '3', '001', '86'),
28 ('5', '3', '003', '80'),
29 ('6', '4', '004', '79'),
30 ('7', '5', '005', '96'),
31 ('8', '6', '006', '80');
11.3、内连接
1 语法:
2 select * from 表1
3 inner join 表2 on 表1.列=表2.列
例1:查询学生信息及学生的成绩
1 select
2 *
3 from
4 students stu
5 inner join scores sc on stu.studentNo = sc.studentNo
扩展:内连接的另一种语法
1 select * from 表1,表2 where 表1.列=表2.列
2 例1:查询学生信息及学生的成绩
3 select
4 *
5 from
6 students stu,
7 scores sc
8 where
9 stu.studentNo = sc.studentNo
例2:查询课程信息及课程的成绩
1 select
2 *
3 from
4 courses cs
5 inner join scores sc on cs.courseNo = sc.courseNo
例3:查询学生信息及学生的课程对应的成绩
1 select
2 *
3 from
4 students stu
5 inner join scores sc on stu.studentNo = sc.studentNo
6 inner join courses cs on cs.courseNo = sc.courseNo
例4:查询王昭君的成绩,要求显示姓名、课程号、成绩
1 select
2 stu.name,
3 sc.courseNo,
4 sc.score
5 from
6 students stu
7 inner join scores sc on stu.studentNo = sc.studentNo
8 where
9 stu.name = '王昭君'
例5:查询王昭君的数据库成绩,要求显示姓名、课程名、成绩
1 select
2 stu.name,
3 cs.name,
4 sc.score
5 from
6 students stu
7 inner join scores sc on stu.studentNo = sc.studentNo
8 inner join courses cs on sc.courseNo = cs.courseNo
9 where
10 stu.name = '王昭君' and cs.name = '数据库'
例6:查询所有学生的数据库成绩,要求显示姓名、课程名、成绩
1 select
2 stu.name,
3 cs.name,
4 sc.score
5 from
6 students stu
7 inner join scores sc on stu.studentNo = sc.studentNo
8 inner join courses cs on sc.courseNo = cs.courseNo
9 wherecs.name = '数据库'
例7:查询男生中最高成绩,要求显示姓名、课程名、成绩
1 select
2 stu.name,
3 cs.name,
4 sc.score
5 from
6 students stu
7 inner join scores sc on stu.studentNo = sc.studentNo
8 inner join courses cs on sc.courseNo = cs.courseNo
9 where
10 stu.sex = '男'
11 order by
12 sc.score desc
13 limit 1
11.4、左链接
1 语法:
2 select * from 表1
3 left join 表2 on 表1.列=表2.列
例1:查询所有学生的成绩,包括没有成绩的学生
1 select
2 *
3 from
4 students stu
5 left join scores sc on stu.studentNo = sc.studentNo
例2:查询所有学生的成绩,包括没有成绩的学生,需要显示课程名
1 select
2 *
3 froms
4 tudents stu
5 left join scores sc on stu.studentNo = sc.studentNo
6 left join courses cs on cs.courseNo = sc.courseNo
11.5、右链接
1 语法:
2 select * from 表1
3 right join 表2 on 表1.列=表2.列
例1:查询所有学生的成绩,包括没有成绩的学生
select
*
from
scores sc
right join students stu on stu.studentNo = sc.studentNo
例2:查询所有学生的成绩,包括没有成绩的学生,需要显示课程名
select
*
from
scores sc
right join students stu on stu.studentNo = sc.studentNo
left join courses cs on cs.courseNo = sc.courseNo
12、自关联
12.1、案例
- 设计省信息的表结构provinces
- id
- ptitle
- 设计市信息的表结构citys citys表的proid表示城市所属的省,对应着provinces表的id值
- id
- ctitle
- proid
- 问题:能不能将两个表合成一张表呢?
- 思考:观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的
- 意义:存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还 要存储区、乡镇信息,都增加新表的开销太大
- 答案:定义表areas,结构如下 因为省没有所属的省份,所以可以填写为null
- id
- atitle
- pid
- 城市所属的省份pid,填写省所对应的编号id
- 这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一 样的,城市信息的pid引用的是省信息的id
- 在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息
准备数据:
1 drop table if exists areas;
2 create table areas(
3 aid int primary key,
4 atitle varchar(20),
5 pid int
6 );
7 insert into areas values
8 ('130000', '河北省', NULL),
9 ('130100', '石家庄市', '130000'),
10 ('130400', '邯郸市', '130000'),
11 ('130600', '保定市', '130000'),
12 ('130700', '张家口市', '130000'),
13 ('130800', '承德市', '130000'),
14 ('410000', '河南省', NULL),
15 ('410100', '郑州市', '410000'),
16 ('410300', '洛阳市', '410000'),
17 ('410500', '安阳市', '410000'),
18 ('410700', '新乡市', '410000'),
19 ('410800', '焦作市', '410000'),
20 ('410101', '中原区', '410100'),
21 ('410102', '二七区', '410100'),
22 ('410301', '洛龙区', '410300');
12.2、自关联
自关联:表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的。(自 己关联自己)
例1:查询河南省所有的市
1 select 2 * 3 from 4 areas as a1 5 inner join areas as a2 on a1.aid=a2.pid 6 where 7 a1.atitle='河南省';
例2:查询郑州市的所有的区
1 select 2 * 3 from 4 areas as a1 5 inner join areas as a2 on a1.aid=a2.pid 6 where 7 a1.atitle='郑州市';
例3:查询河南省的所有的市区
1 select 2 * 3 from 4 areas as a1 5 inner join areas as a2 on a1.aid=a2.pid 6 inner join areas as a3 on a2.aid=a3.pid 7 where 8 a1.atitle='河南省'
13、子查询
13.1、子查询介绍
子查询:在一个 select 语句中,嵌入了另外一个 select 语句,那么嵌入的 select 语句称之为子查 询语句
主查询:外层的 select 语句称之为主查询语
13.1.1、主查询和子查询的关系
- 子查询是嵌入到主查询中的
- 子查询是辅助主查询的,要么充当条件,要么充当数据源
- 子查询是可以独立使用的语句,是一条完整的 select 语句
13.2、子查找充当条件
例1:查询大于平均年龄的学生
1 查询班级学生平均年龄 2 select avg(age) from students 3 4 查询大于平均年龄的学生 5 select * from students where age > 21.4167
6 select * from students where age > (select avg(age) from students);
例2:查询王昭君的成绩,要求显示成绩
1 学生表中查询王昭君的学号
2 select studentNo from students where name = '王昭君'
3
4 成绩表中根据学号查询成
5 select * from scores where studentNo = '001'
6
7 select * from scores
8 where studentNo = (select studentNo from students where name = '王昭君')
例1和例2中:子查询返回的结果只有一个值(一行一列),这种称之为标量子查询
例3:查询18岁的学生的成绩,要求显示成绩
1 学生表中查询18岁的学生的学号
2 select studentNo from students where age=18
3
4 成绩表中根据学号查询成绩
5 select * from scores where studentNo in ('002','006')
6
7 select * from scores
8 where studentNo in (select studentNo from students where age=18)
例3中:子查询返回的结果是一列数据(一列多行),这种称之为列子查询
例4:查询和王昭君同班、同龄的学生信息
select class,age from students where name='王昭君'
select * from students where class='1班' and age=20
select * from students where (class,age)=('1班',20)
select * from students
where (class,age)=(select class,age from students where name='王昭君')
例4中:子查询返回的结果是一行(一行多列),这种称之为行子查询
13.3、子查询充当数据源
例5:查询数据库和系统测试的课程成绩
1 select
2 *
3 from
4 scores s
5 inner join
6 (select * from courses where name in ('数据库','系统测试')) c
7 on s.courseNo = c.courseNo
例5中:子查询返回的结果是多行多列(相当于一个表),这种称之为表级子查询
13.4、子查询中特定关键字使用
- in 范围
- 格式: 主查询 where 条件 in (列子查询)
- any | some 任意一个
- 格式: 主查询 where 列 = any (列子查询)
- 在条件查询的结果中匹配任意一个即可,等价于 in
- all
- 格式: 主查询 where 列 = all(列子查询) : 等于里面所有
- 格式: 主查询 where 列 <>all(列子查询) : 不等一其中所有
1 select * from students
2 where age in (select age from students where age between 18 and 20)
14、查询演练
14.1、数据准备
创建表
- 部门 departments
- 员工 employees
- 工资表 salary
部门表
1 drop table if exists departments;
2 create table departments (
3 deptid int(10) primary key,
4 deptname varchar(20) not null -- 部门名称
5 );
6 insert into departments values ('1001', '市场部');
7 insert into departments values ('1002', '测试部');
8 insert into departments values ('1003', '开发部');
员工表
1 drop table if exists employees;
2 create table employees (
3 empid int(10) primary key,
4 empname varchar(20) not null, -- 姓名
5 sex varchar(4) default null, -- 性别
6 deptid int(20) default null, -- 部门编号
7 jobs varchar(20) default null, -- 岗位
8 politicalstatus varchar(20) default null, -- 政治面貌
9 leader int(10) default null
10 );
11 insert into employees values ('1', '王昭君', '女', '1003', '开发', '群众', '9');
12 insert into employees values ('2', '诸葛亮', '男', '1003', '开发经理', '群众', null);
13 insert into employees values ('3', '张飞', '男', '1002', '测试', '团员', '4');
14 insert into employees values ('4', '白起', '男', '1002', '测试经理', '党员', null);
15 insert into employees values ('5', '大乔', '女', '1002', '测试', '党员', '4');
16 insert into employees values ('6', '孙尚香', '女', '1001', '市场', '党员', '12');
17 insert into employees values ('7', '百里玄策', '男', '1001', '市场', '团员', '12');
18 insert into employees values ('8', '小乔', '女', '1002', '测试', '群众', '4');
19 insert into employees values ('9', '百里守约', '男', '1003', '开发', '党员', '9');
20 insert into employees values ('10', '妲己', '女', '1003', '开发', '团员', '9');
21 insert into employees values ('11', '李白', '男', '1002', '测试', '团员', '4');
22 insert into employees values ('12', '孙膑', '男', '1001', '市场经理', '党员', null);
工资表
1 drop table if exists salary;
2 create table salary (
3 sid int(10) primary key,
4 empid int(10) not null,
5 salary int(10) not null -- 工资
6 );
7 insert into salary values ('1', '7', '2100'); insert into salary values ('2', '6', '2000');
8 insert into salary values ('3', '12', '5000'); insert into salary values ('4', '9', '1999');
9 insert into salary values ('5', '10', '1900'); insert into salary values ('6', '1', '3000');
10 insert into salary values ('7', '2', '5500'); insert into salary values ('8', '5', '2000');
11 insert into salary values ('9', '3', '1500'); insert into salary values ('10', '8', '4000');
12 insert into salary values ('11', '11', '2600'); insert into salary values ('12', '4', '5300');
14.2、练习
1)列出总人数大于4的部门号和总人数
1 select deptid, count(*) from employees e group by deptid having count(*)>4
2)列出开发部和和测试部的职工号、姓名
1 select e.empid,d.empname from employees e
2 inner join departments d on e.deptid = d.deptid
3 where d.deptname in ('开发部','测试部')
3)求出各部门党员的人数,要求显示部门名称
select d.deptname,count(*) from employees e
inner join departments d on e.deptid=d.deptid
where e.politicalstatus = '党员' group by e.deptid
4)列出市场部的所有女职工的姓名和政治面貌
1 select e.empname,e.politicalstatus from employees e
2 inner join departments d on e.deptid = d.deptid
3 where e.sex= '女' and d.deptname = '市场部'
5)显示所有职工的姓名、部门名和工资数
1 select e.empname,d.deptname,s.salary from employees e
2 inner join departments d on e.deptid = d.deptid
3 inner join salary s on e.empid = s.empid
6)显示各部门名和该部门的职工平均工资
1 select d.deptname, avg(s.salary) from departments d
2 inner join employees e on d.deptid = e.deptid
3 inner join salary s on e.empid = s.empid group by d.deptname
7)显示工资最高的前3名职工的职工号和姓名
1 select e.empid, e.empname,s.salary from salary s
2 inner join employees e on s.empid = e.empid order by s.salary desc limit 3
8)列出工资在1000-2000之间的所有职工姓名
1 select e.empname,s.salary from salary s
2 inner join employees e on s.empid = e.empid
3 where s.salary between 1000 and 2000
9)列出工资比王昭君高的员工
1 select * from employees e
2 inner join salary s on e.empid=s.empid
3 where s.salary>
4 (select s.salary from employees e
5 inner join salary s on e.empid=s.empid
6 where e.empname='王昭君')
10)列出每个部门中工资小于本部门平均工资的员工信息
1 select * from employees e
2 inner join salary s on e.empid=s.empid
3 inner join
4 (select d.deptid,d.deptname, avg(s.salary) avg_salary from departments d
5 inner join employees e on d.deptid = e.deptid
6 inner join salary s on e.empid = s.empid group by d.deptname) temp
7 on e.deptid=temp.deptid
8 where s.salary<temp.avg_salary
二、MySQL高级
1、数据库设计
1.1、E-R模型
- E 表示 entry,实体:一个数据对象,描述具有相同特征的事物
- R 表示 relationship,联系:表示一个或多个实体之间的关联关系,关系的类型包括包括一对一、一对多、多对多
- 属性:实体的某一特性称为属性
1.1.1、一对一

1.1.2、一对多

1.1.3、多对多
- 想一想:举些例子,满足一对一、一对多、多对多的对应关系
2、命令行客户端
2.1、链接服务器
1、进入 MySQL 的 bin 目录 cd C:\Program Files (x86)\MySQL\MySQL Server 5.1\bin 2、连接 MySQL mysql -uroot -p

2.2、操作数据库
- 查看所有数据库
show databases;
- 使用数据库
use 数据库名;
- 查看当前使用的数据库
select database();
- 创建数据库
create database 数据库名 charset=utf8;
例:
create database ceshi charset=utf8;
- 删除数据库
drop database 数据库名;
例:
drop database ceshi;
2.3、操作数据表
- 查看当前数据库中所有表
show tables;
- 查看表结构
desc 表名;
- 查看表的创建语句
show create table 表名;
例:
show create table students;
3、外键
3.1、外键(foreign key)
- 如果一个实体的某个字段指向另一个实体的主键,就称为外键。
- 被指向的实体,称之为主实体(主表),也叫父实体(父表)。
- 负责指向的实体,称之为从实体(从表),也叫子实体(子表)
- 对关系字段进行约束,当为从表中的关系字段填写值时,会到关联的主表中查询此值是否存在,如果存在则填 写成功,如果不存在则填写失败并报错
3.1.1、语法
设置外键约束
- 方式一:创建数据表的时候设置外键约束
1 create table class(
2 id int unsigned primary key auto_increment,
3 name varchar(10)
4 );
5
6 create table stu(
7 name varchar(10),
8 class_id int unsigned,
9 foreign key(class_id) references class(id)
10 );
11
12 foreign key(自己的字段) references 主表(主表字段)
- 方式二:对于已经存在的数据表设置外键约束
1 alter table 从表名 add foreign key (从表字段) references 主表名(主表字段);
2
3 alter table stu add foreign key (class_id) references class(id);
查看外键
1 show create table 表名
删除外键
1 -- 需要先获取外键约束名称
2 show create table stu;
3 -- 获取名称之后就可以根据名称来删除外键约束
4 alter table 表名 drop foreign key 外键名称;
5
6 alter table stu drop foreign key stu_ibfk_1;
在实际开发中,很少会使用到外键约束,会极大的降低表更新的效率
4、索引
- 思考:在字典中是如何找到一个汉字?
- 一般的应用系统对比数据库的读写比例在10:1左右,而且插入操作和更新操作很少出现性能问题,遇到 最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重
- 当数据库中数据量很大时,查找数据会变得很慢
- 优化方案:索引
4.1、索引演示
导入测试表test_index
右键点击某个数据库->运行sql文件->选择test_index.sql->点击开始
查询
- 开启运行时间监测:
set profiling=1;
- 查找第1万条数据test10000
select * from test_index where title='test10000';
- 查看执行的时间:
show profiles;
- 为表title_index的title列创建索引:
create index title_index on test_index(title(10));
- 执行查询语句:
select * from test_index where title='test10000';
- 再次查看执行的时间
show profiles;
4.2、索引语法
- 查看索引
show index from 表名;
- 创建索引
方式一:建表时创建索引
create table create_index(
id int primary key,
name varchar(10) unique,
age int,
key (age)
);
方式二:对于已经存在的表,添加索引
如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
字段类型如果不是字符串,可以不填写长度部分
create index 索引名称 on 表名(字段名称(长度))
例:
create index age_index on create_index(age);
create index name_index on create_index(name(10));
- 删除索引:
drop index 索引名称 on 表名;
4.3、索引缺点
- 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE,因 为更新表时,MySQL不仅要保存数据,还要保存一下索引文件
- 但是,在互联网应用中,查询的语句远远大于增删改的语句,甚至可以占到80%~90%,所以也不要太在意,只是在大 数据导入时,可以先删除索引,再批量插入数据,最后再添加索引
4.4、分析查询
explain
select * from test_index where title='test10000'

浙公网安备 33010602011771号