4.表操作
1.数据库设计
系统设计中一个重要的环节就是数据库设计.
数据库设计的时候需要先进行数据建模(实体关系图 E-R图)
数据建模的依据就是前期所做的需求分析
实体-关系图(Entity Relationship Diagram),也称为E-R图,提供了表示实体、属性和关系的方法,用来描述现实世界的概念模型。
构成E-R图的基本要素是实体、属性和关系
实体(Entity):实体用来表示具有相同特征和性质的事物(类似于java的类),实体由实体名和实体属性来表示。
属性(Attribute):实体所具有的某一特性,一个实体可以有若干个属性
关系(Relationship):实体彼此之间相互连接的方式称为关系。一般可分为以下 3 种类型:
一对一关系 (1 ∶ 1)
一对多关系 (1 ∶ N)
多对多关系 (M ∶ N)
may-be 和 must-be
在实体与实体之间的关系中,都会存在着may-be和must-be这俩种情况,例如:
系统中有顾客和订单俩个实体(1:N关系),一个顾客对应多个订单,一个订单对应一个顾客,而且一个顾客可以(may be)没有订单和他对应,一个订单一定(must be)会有顾客和它对应.
ER图中符号的表示
1) # : 唯一, 以后可能表示为主键
2) * : 非空
3) o : 可有可无
4) 虚线: may be 顾客这边虚线,顾客可能没有订单
5) 实线: must be 订单这边实线,订单一定是属于某个客户。
6) 竖杠(|): 代表要强制在(|)一方建立一个联合主键,将对方ID拿过来做联合主键
7) 伞状图标代表多的一方,不是伞状图标则代表一的一方
数据库设计
数据建模完成之后,可以把ER图转换成数据中的表
1.实体的名字转换为表的名字
2.实体的属性转换为表中的列
3.具有唯一特点的属性设置为表中的主键
4.根据实体之间的关系设置为表中某列为外键列(主外键关联)
注意:第四步主要是:实体关系—>表关系
2.数据库范式
设计关系数据库时,遵从不同的规范要求,才能设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:
第一范式(1NF)
第二范式(2NF)
第三范式(3NF)
巴斯-科德范式(BCNF)
第四范式(4NF)
第五范式(5NF,又称完美范式)
注:满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了
第一范式:
一个表中,每个列里面的值是不能再分割的.
例如:我们设计的表中有一个列是:爱好
这个列的值可能会是这样:足球篮球乒乓球
但是这值是可以再分割的:足球、篮球、乒乓球
所以这种设计是不满足第一范式
第二范式:
第二范式是在满足第一范式的基础上
表中的非主键列都必须依赖于主键列
例如:
订单表: 订单编号 是主键
订单编号 订单名称 订单日期 订单中产品的生产地
这几个非主键列中,产品生产地是不依赖于订单编号的,所以这种设计是不满足第二范式
第三范式:
第三范式是在满足第二范式的基础上
表中的非主键列都必须直接依赖于主键列,而不能间接的依赖.
(不能产生依赖传递)
例如:
订单表: 订单编号 是主键
订单编号 订单名称 顾客编号 顾客姓名
顾客编号依赖于订单编号,顾客姓名依赖于顾客编号,从而顾客姓名间接的依赖于订单编号,那么这里产生了依赖传递,所以这个设计是不满足第三范式的
了解主键和外键
主键:
1.能做主键的列必要满足非空唯一的特点
2.只要满足非空唯一的任何列都可以做主键
3.可以让表中一个有意义的列做主键,比如说学号,它既表示学生学号又作为表中的主键,因为这个列满足非空唯一的条件
4.也可以找一个没有意义的列做主键,就是用来唯一标识一行记录的
5.我们可以让多个列联合在一起做表中的主键,那么它就是联合主键,要求这几个列的值联合在一起是非空唯一的
外键:
1.表中的某一个列声明为外键列,一般这个外键列的值都会引用于另外一张表的主键列的值(有唯一约束的列就可以,不一定非要引用主键列)
2.另外一张表的主键列中出现过的值都可以在外键列中使用,没有出现过的值,都不能使用
3.外键列值也可以为空的,提前是这个外键列在表中不做主键,因为我们也可以把表中的外键列当做主键来使用(只有满足非空唯一的要求就可以)
4.如果把B表中的联合主键的值引用到A表中做外键,因为是俩个列在B表中做联合主键,那么A表引用过来的时候也要把俩个列的值都引用过来,那么它们在A表中就会作为一个联合外键出现
3.具体操作
1.创建表
create table if not exists table_name(
列名 数据类型 [列级约束],
列名 数据类型 [约束],
.
.
.
列名 数据类型 [约束],
constraint 约束名1 表级约束1,
constraint 约束名2 表级约束2
);
//特殊的建表:建立一张表和s_user一模一样的表
create table 表名 as select语句;
例如1:s_user的表结构和表中的数据全部复制过来
create table s_test1
as
select * from s_user;
例如2:只拿来s_user的表结构,没有数据
create table s_test2
as
select * from s_user
where 1=2;
例如3:只复制表中某几个列以及数据
create table s_test3
as
select userId,userName,password from s_user;
2.查看表结构
describe tableName;
desc tableName;
show create table tableName;
3.删除表
drop table tableName;
drop table if exists tableName;
4.修改表
alter table 表名 add|drop|modify|change 属性名|索引名|约束名
修改表名:alter table old_table_name rename [to] new_table_name;
增加字段:alter table table_name add 属性名 属性类型 [first];
alter table table_name add 属性名 属性类型 after 属性名;
删除字段:
alter table table_name drop 属性名;
修改字段:
alter table table_name modify 属性名 数据类型;
alter table table_name change 旧属性名 新属性名 旧数据类型;
alter table table_name change 旧属性名 新属性名 新数据类型;
alter table table_name modify 属性名1 数据类型 [first|after 属性名];
修改表编码格式:
alter table <表名> character set utf8;
5.表的约束
完整性约束
not null 非空约束
default 默认值
unique [(UK)] 唯一约束
primary key[(PK)] 主键约束
foreign key[(FK)] 外键约束
auto_increment 自动增长
Mysql不支持check约束,不生效。
1.根据约束数据列限制,约束分为:
单列约束(列级约束),即每个约束只约束一列数据;
多列约束(表级约束),即每个约束可以约束多列数据;
2.根据约束的位置,约束分为:
列级约束(因为是跟在列的声明后面写的)
表级约束(因为是在全部列声明完之后写的)
列级约束和表级约束都是对列中的值进行约束的,例如:列的值不能为空,列的值必须是唯一的等等。
constraint关键字
1.constraint是约束的意思.
2.建表的时候可以给约束起一个名字,这个名字起的规律一般会是:表名_列名_约束类型.
3.如果没有给约束起名字,那么系统也会给这个约束起一个默认的名字,这不过这个默认的名字对我们来说并不友好(我们看不懂).
4.将来我们可以根据我们之前给约束起好的名字而找到这个约束,然后进行修改.
可以在创建表的时候添加约束,也可以在创建表之后,修改表,给表添加/删除约束。
/*添加主键约束:*/
alter table 表名 add primary key(主键列名);
/*删除主键约束:*/
alter table 表名 drop primary key;
/*添加唯一约束:*/
alter table 表名 add constraint 索引名 unqiue(唯一列名);
/*删除唯一约束:*/
alter table 表名 drop index 索引名;
drop index 索引名 on 表名;
/*添加外键约束:*/
alter table 表名 add constraint 外键索引名 foreign key(外键列名) references 外键表(外键表中的列名);
/*删除外键约束:*/
alter table 表名 drop foreign key 外键索引名;
drop index 外键索引名 on 表名;
#外键中的级联关系有以下几种情况:
#ON DELETE CASCADE 删除主表中的数据时,从表中的数据随之删除
#ON UPDATE CASCADE 更新主表中的数据时,从表中的数据随之更新
#ON DELETE SET NULL 删除主表中的数据时,从表中的数据置为空
#默认 删除主表中的数据前需先删除从表中的数据,否则主表数据不会被删除
注:
1.列级约束也称为行级约束.
2.NOT NULL约束只能在列级别定义,作用在多个列上的约束只能定义在表级别,例如复合主键约束.
3.列级别上不能定义外键约束,并且不能给约束起名字,由MySQL自动命名(NOT NULL除外.
4.表级别上定义的约束可以给约束起名字.
6.练习
/*练习1:构建一张用户表:用户名Id 用户名 密码 手机号码 邮箱 个人简介(备注)*/
create table s_user(
userId int primary key auto_increment,
userName varchar(10) unique not null,
password varchar(10) not null,
phone char(11) unique not null,
email varchar(30) not null,
gender char(1) default '男',
demo varchar(250) default '这个人很懒,没有填写个性签名。'
);
insert into s_user(userName,password,phone,email) values('briup1','briup123','18230981230','1728777@qq.com');
/*练习2:构建一张订单表*/
create table book_user(
userId int primary key auto_increment,
userName varchar(10) ,
password varchar(20) not null,
demo varchar(50) default '很懒,没有填写签名。',
constraint userName_unique unique(userName)
);
create table book_order1(
orderId int primary key auto_increment,
price double not null,
orderTime datetime not null,
userId int references user(userId)
);
create table book_order3(
orderId int primary key auto_increment,
price double not null,
orderTime datetime not null,
userId int,
constraint userId_fk foreign key(userId) references book_user(userId)
);
5.数据操作
1.插入数据
insert into tbale_name(field1,field2...,fieldn) values(value1,value2...,valuen),(value1,value2...,valuen)...,(value1,value2...,valuen);
insert into tbale_name(field1,field2...,fieldn) select field1,field2...,fieldn from table_name2 where ...;
2.更新数据
update table_name set field1=value1,field2=value2,...,fieldn=valuen [where condition];
3.删除数据
delete from table_name [where condition];
truncate table table_name;
4.查询数据
4.1单表查询
select [distinct] field1,field2...,fieldn|*
from table_name
where 限制行条件
group by 分组列名
having 限制分组之后的条件
order by 排序列 [asc|desc];
注:除了select和from之外其他的都不是必须的。
假如select…from…后面的语句都出现了,那么他们的执行顺序为:
where–>group by分组–>执行组函数–>having筛选->order by/select
1.关系运算符: + - * / %
2.条件语句
关系运算符和逻辑运算符 && || & | and or
between … and …
is [not] null
[not] in (value1,value2…,valuen)
[not] like '%_%’
3.排序
order by 列1 asc,列2 desc;
4.限制数据行数
limit [offser_start,]row_count;
select * from s_dept where dept_id is null limit 2;
select * from s_dept where dept_id is null limit 0,5;
分页展示数据
两个参数
p页码
r每页显示的行数
select * from 表 limit (p-1)*r,r
每页展示5条
第一页 limit 0,5
第二页 limit 5,5
第三页 limit 10,5
第N页 limit (p-1)*r,r
例如:
select * from bm_course limit 起始行,每页行数;
select * from bm_course where rowNum>=起始行 limit 每页行数;
select @rowNum:=@rowNum+1 rowId,a.*
from bm_course a,(select @rowNum:=0) b)
where rowId >= 起始页 limit 每页行数;
/*测试limit分页优化:*/
create table pageTest as select * from bm_course;
insert into pageTest select * from pageTest; 执行N次插入数据
create table pageRowId as select @rowNum:=@rowNum+1 rowId,p.* from pageTest p , (select @rowNum:=0) r;
alter table pageRowId add index rowIdIndex(rowId);
select count(*) from pageRowId;
+----------+
| count(*) |
+----------+
| 851968 |
+----------+
select * from pageRowId limit 10, 100;
select * from pageRowId where rowId >= (≠select rowId from pageRowId limit 10,1) limit 100;
select * from pageRowId where rowId >= 10 limit 100;
select * from pageRowId limit 1000, 100;
select * from pageRowId where rowId >= (select rowId from pageRowId limit 1000,1) limit 100;
select * from pageRowId where rowId >= 1000 limit 100;
select * from pageRowId limit 100000, 100;
select * from pageRowId where rowId >= (select rowId from pageRowId limit 100000,1) limit 100;
select * from pageRowId where rowId >= 100000 limit 100;
select * from pageRowId limit 800000, 100;
select * from pageRowId where rowId >= (select rowId from pageRowId limit 800000,1) limit 100;
select * from pageRowId where rowId >= 800000 limit 100;
select * from pageRowId where rowId between 800000 and 800100;
5.统计函数和分组函数
分组函数:
avg sum max min count
语法格式:
select 组函数(field|*)
from table_name
where condition
group by field1,field2,field3
[having condition];
需要注意:
1.组函数出现的位置:
1.select后面
2.having后面
3.order by后面
4.where后面一定【不能】出现组函数
注意:如果select/having语句后面出现了组函数,那么select/having后面没有被组函数修饰的列,就必须出现在group by 后面
2.where和having对比:
1.where和having都是做条件筛选的
2.where执行的时间比having要早
3.where后面不能出现组函数
4.having后面可以出现组函数
5.where语句要紧跟from后面
6.having语句要紧跟group by后面
3.group by和having的关系:
1.group by可以单独存在,后面可以不出现having语句
2.having不能单独存在,有需要的话,必须出现在group by后面
4.order by语句
1.如果sql语句中需要排序,那么就一定要写在sql语句的最后面
2.order by后也可以出现组函数
4.2多表查询
多表查询,又称表联合查询,即一条sql语句涉及到的表有多张,数据通过特定的连接进行联合显示.
1.关系数据的各种操作
笛卡尔积 cartesian product
在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y.
假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
在数据库中,如果直接查询俩张表,那么其查询结果就会产生笛卡尔积
select *from s_emp,s_dept;
1.1连接查询 join
1.内连接inner join:只保留表关系中所有匹配的数据记录,舍弃不匹配的数据记录。
1.自然连接 natural join:根据表关系中相同名称的字段自动进行记录匹配,然后去掉重复的字段。
2.等值连接:表关系的笛卡尔积中,选择所匹配字段值相等(=)的数据记录。
例如:查询开设课程的课程名称。
开设课程表 bm_course_choice id course_id
课程管理表 bm_course courseNum sportsEvent
select course_id,sportsEvent
from bm_course_choice bcc,bm_course bc
where bcc.course_id=bc.couserNum;
3.不等值连接:选择所匹配字段值不想等(!=)的数据记录。
例如:假设数据库中还有一张工资等级表:salgrade s
where
工资等级表salgrade:
gradeName列表示等级名称
losal 列表示这个级别的最低工资数
hisal 列表示这个级别的最高工资数
表中的数据类似于下面内容:
id salgrade losal hisal;
1 初级程序员 2000 4000
2 中级程序员 4000 6000
s_emp
张三 2500
李四 4800
select name,salary,salgrade
from s_emp e, salgrade s
where e.salary >= s.losal and e.salary < s.hisal;
select name,salary,salgrade
from s_emp e, salgrade s
where e.salary between s.losal and s.hisal;
查询出员工的名字、职位、工资、工资等级名称
select e.name, e.title, e.salray, s.gradeName
from s_emp e, salgrade s
where e.salray BETWEEN s.losal AND s.hisal
2.外连接outer join:不仅保留表关系中所有匹配的数据记录,而且还会保留部分不匹配的数据记录。
注意:outer可以省去不写
1.左外连接:保留表关系中所有匹配的数据记录,包含关联左边表中不匹配的数据记录。
…
from 表1 left [outer] join 表2 on 条件
…
例如:查询所有员工 以及对应的部门的名字,没有部门的员工也要显示出来
2.右外连接:保留表关系中所有匹配的数据记录,包含关联右边表中不匹配的数据记录。
...
from 表1 right [outer] join 表2 on 条件
...
例如:查询所有员工 以及对应的部门的名字,没有任何员工的部门也要显示出来
select name,dept_id,name
from s_emp right outer join s_dept
on s_emp.dept_id=s_dept.id ;
3.全连接:保留表关系中所有匹配的数据记录,包含关联左右两边表中不匹配的数据记录。
...
from 表1 full [outer] join 表2 on 条件
...
例如:查询所有员工 以及对应的部门的名字,没有任何员工的部门也要显示出来,没有部门的员工也要显示出来
select name,dept_id,name
from s_emp full outer join s_dept
on s_emp.dept_id=s_dept.id;
3.交叉连接 cross join:表关系笛卡尔积后数据记录,不需要任何匹配条件,有时候该操作的结果没有任何实际意义。
4.自连接:一张表,自己和自己连接
例如:查询每个员工的名字以及员工对应的经理的名字
select s1.name,s2.name manager_name
from s_emp s1,s_emp s2
where s1.manager_id = s2.id;
1.2对查询结果集的操作
如果有俩条sql语句,每一条sql都可以查询出一个结果,这个被称之为结果集。那么我们可以使用下面的关键字对俩个结果集进行操作
union 获得俩个结果集的并集
select sportsEvent,week
from bm_course
where week=‘周一’ or week=‘周二’
union
select sportsEvent,week
from bm_course
where week=‘周二’ or week=‘周三’;
union all 把俩个结果集 合在一起显示出来
select sportsEvent,week
from bm_course
where week=‘周一’ or week=‘周二’
union all
select sportsEvent,week
from bm_course
where week=‘周二’ or week=‘周三’;
minus 差集 第一个结果集除去第二个结果集和它相同的部分
Mysql不支持minus
select c1.* from (select courseNum,sportsEvent,week
from bm_course
where week=‘周一’ or week=‘周二’) c1 left join
(select courseNum,sportsEvent,week
from bm_course
where week=‘周二’ or week=‘周三’) c2 on c1.courseNum=c2.courseNum where c2.week is null;
intersect 获得俩个结果集的交集
Mysql不支持intersect
select c1.* from (select courseNum,sportsEvent,week
from bm_course
where week='周一' or week='周二') c1 join
(select courseNum,sportsEvent,week
from bm_course
where week='周二' or week='周三') c2 on c1.courseNum=c2.courseNum;
注意:
1.前提条件 俩个结果集中【查询的列】要完全一致
2.union和union all关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同。
2.1、对重复结果的处理:union在进行表链接后会筛选掉重复的记录,union all不会去除重复记录。
2.2union all只是简单的将两个结果合并后就返回。
2.3从效率上说,union all要比union快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用union all。
2.子查询:指在一个查询之中嵌套了其他的若干查询,即在一个select查询语句的where或from子句中包含另一个select查询语句。在查询语句中,外层select查询语句称为主查询,where子句中的select查询语句被称为子查询,也被称为嵌套查询。
select
from 表|(select子句)
where 列 >=|in (select子句)
##### 5.练习
1.请查询课程管理表中的数据。
bm_course 16条数据
courseNum 课程编号
sportsEvent 课程名称
location 课程地点
week 课程时间
fee 价格
2.请查询本学期开设课程表中的数据。
bm_course_choice
desc bm_course_choice;
select count(*) from bm_course_choice;
6条数据 id course_id
3.请查询公告表中的数据。
4.请查询用户表中的数据。
bm_registration
stuName 学生名字
select * from bm_registration \G;
5.请查询周一开设的课程名,课程地点以及价格。
sportsEvent location week fee
--------
select *
from bm_course
where week='周一';
--------
select sportsEvent,location,fee,week from bm_course bc , bm_course_choice bcc where bcc.course_id=bc.courseNum and week='周一';
6.请查询所有乒乓球课程的课程地点,开课日期,并按照价格降序排列。
sportsEvent location week fee
思考过程:
1.列:课程地点,开课日期 ,课程名字, 价格;
2.条件:乒乓球课程;
3.其他:按照价格降序排列;
select location,week,sportsEvent,fee
from bm_course
where sportsEvent like '%乒乓球%'
order by fee desc;
7.按照课程编号升序排列,分页展示课程管理表中的数据,每页展示5条数据。
select * from bm_course order by id asc limit (页数-1)*每页展示的条数,每页展示的条数\G
select * from bm_course where id >= (select id from bm_course limit (页数-1)*每页展示的条数,1) limit 每页展示的条数\G
select * from bm_course where id between (页数-1)*每页展示的条数+1 and 页数*每页展示的条数;
select * from bm_course order by id asc limit 10,5\G
select * from bm_course where id >=(select id from bm_course limit 10,1) limit 5\G
select * from bm_course where id between 11 and 15;
8.请查询本学期开设课程表中的课程名称,课程编号,价格。
bm_course_choice id course_id schoolterm_id year_id
select course_id,sportsEvent,fee from bm_course_choice ,bm_course c where course_id=c.id;
9.请模拟用户选择课程,向用户选择课程表中保存3条数据。
insert into bm_coursechoice_user(id,insertTime,coursechoice_id,user_id,amount) values(1,now(),1,1,100);
insert into bm_coursechoice_user(id,insertTime,coursechoice_id,user_id,amount) values(2,now(),4,1,770);
insert into bm_coursechoice_user(id,insertTime,coursechoice_id,user_id,amount) values(3,now(),1,2,100);
10.请查询各门课程已经报名的用户人数。
报名表 bm_coursechoice_user
coursechoice_id=bcc.id and bcc.course_id=bc.courseNum
开设课程信息 bm_course_choice
course_id
课程信息 bm_course
sportsEvent courseNum
组函数:count(*)
分组: 课程编号
select bc.id,bc.sportsEvent,count(*) sum
from bm_coursechoice_user bcu,bm_course_choice bcc,bm_course bc
where bcu.coursechoice_id=bcc.id and bcc.course_id=bc.id
group by bc.id,bc.sportsEvent;
select coursechoice_id,count(*) from bm_coursechoice_user group by coursechoice_id;
11.请查询各门课程已经报名的用户人数,以及对应的课程名称。
select sportsEvent,num from bm_course c,bm_course_choice cc,(select coursechoice_id,count(*) num from bm_coursechoice_user group by coursechoice_id) tmp where c.id=cc.course_id and cc.course_id=coursechoice_id;
12.请查询"李祺烁"已经报名成功的课程信息(课程名称,课程地址,课程日期,课程价格)。
1.获取"李祺烁"的用户编号
select id from bm_registration where stuName='李祺烁';
2.根据用户编号在用户报名课程表中查询该用户报名的开设课程编号
select coursechoice_id from bm_coursechoice_user where user_id=(第一步的结果);
select coursechoice_id from bm_coursechoice_user where user_id=(select id from bm_registration where stuName='李祺烁');
3.根据报名的开设课程编号在开设课表中查询对应课程编号
select course_id
from bm_course_choice
where id in (第二步结果);
4.根据报名的课程编号在课程管理表中查询对应课程的具体信息
select sportsEvent,location,week,fee from bm_course where id in (第三步结果);
列:sportsEvent,location,week,fee
表:bm_course bc,bm_registration br,bm_coursechoice_user bcu,bm_course_choice bcc
多表及联条件:br.id=bcu.user_id
and bcu.coursechoice_id=bcc.id
and bcc.course_id=bc.id
查询条件:stuName='李祺烁'
select sportsEvent,location,week,fee
from bm_course bc,bm_registration br,bm_coursechoice_user bcu,bm_course_choice bcc where br.id=bcu.user_id
and bcu.coursechoice_id=bcc.id
and bcc.course_id=bc.id and stuName='李祺烁';
13.请查询课程管理表中最大的课程价格,并且显示出这个最大的课程价格的课程名字.
1.使用连接查询
1.查询课程管理表中最大的课程价格
select max(fee+0)
from bm_course;
2.加上课程名字
select max(fee+0),sportsEvent
from bm_course;
3.select后面出现组函数,没有被组函数修饰的列放到group by后面,但是发现查询结果并不是想要结果
select max(fee+0),sportsEvent
from bm_course
group by sportsEvent;
4.修改为多表查询(起别名),从bc表中查询出最大的课程价格是多少,然后再和bc2表连接起来,选出bc2表中这个最大课程价格的员工名字
select max(bc.fee+0),bc2.sportsEvent
from bm_course bc,bm_course bc2
where max(bc.fee+0)=bc2.fee
group by bc2.sportsEvent;
5.where后面不能出现组函数,所以改为having
select max(bc2.fee+0),bc.sportsEvent
from bm_course bc,bm_course bc2
group by bc2.sportsEvent,bc.fee
having bc2.fee=max(bc.fee+0);
2.使用子查询
1.查询课程管理表中最大的课程价格
select max(fee+0)
from bm_course;
2.查询最大的课程价格对应的课程编号以及对应的课程名字
select courseNum,sportsEvent,fee
from bm_course
where fee = (select max(fee+0)
from bm_course);
14.请查询选择兵乓球课程的用户信息。
7.索引操作
1.索引是一种排好序的数据结构。
2.索引的作用是帮助数据库提高数据检索效率,但是会降低插入删除更新表的速度以及索引过多则会占据许多磁盘空间。
3.Mysql支持4类索引:单列索引(普通索引,唯一索引,主键索引),多列索引,全文索引(只适合只在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引),空间索引( 空间索引是对空间数据类型的字段建立的索引,只在MyISAM引擎上才能使用,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。)
4.索引的遵循原则:
1、最左侧原则,表的最左侧的一列,往往数据不会发生改变,不影响其他列的数据;
2、命名短小原则,索引命名过长会使索引文件变大,损耗内存。
5.适合创建索引的场景:
1.对经常用于查询的字段应该创建索引,即在where子句种出现的字段。
2.在一个字段上不同值较多可以建立索引。
3.在分组的字段,即在group by子句种出现的字段。
4.存在依赖关系得到子表和父表之间的联合查询,即主键或外键字段。
5.设置唯一完整性约束的字段。
6.不适合创建索引的场景:
1.对查询很少被使用的字段时不要建立索引。
2.在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。
3.对经常更新的表就避免对其进行过多的索引。
4.数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。