Mysql知识树整理【3】 ---高级

  • 实体与实体之间有3种对应关系,这些关系也需要存储下来
  • 在开发中需要对存储的数据进行一些处理,用到内置的一些函数
  • 视图用于完成查询语句的封装
  • 事务可以保证复杂的增删改操作有效

 

创建表的语句如下:

Create table scores(

Id int primary key auto_increment,

stuid int,

subid int,

score decimal(5,2)

);

此时插入或者修改数据时,如果stuid的值在students表中不存在则会报错

在创建表示可以直接创建约束

create table scrores(

Id int primary key auto_increment,

Stuid int,

Subid int,

Score decimal(5,2),

Foreign key(stuid) references students(id),

Foreign key(subid) references subjects(id)

);

先看个问题

  • 问:查询每个学生每个科目的分数
  • 分析:学生姓名来源于students表,科目名称来源于subjects,分数来源于scores表,怎么将3个表放到一起查询,并将结果显示在同一个结果集中呢?
  • 答:当查询结果来源于多张表时,需要使用连接查询
  • 关键:找到表间的关系,当前的关系是
    • students表的id---scores表的stuid
    • subjects表的id---scores表的subid
  • 则上面问题的答案是:

select students.sname,subjects.stitle,scores.score

from scores

inner join students on scores.stuid=students.id

inner join subjects on scores.subid=subjects.id;

  • 结论:当需要对有关系的多张表进行查询时,需要使用连接join

连接查询

  • 连接查询分类如下:
    • 表A inner join 表B:表A与表B匹配的行会出现在结果中
    • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充
    • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充
  • 在查询或条件中推荐使用“表名.列名”的语法
  • 如果多个表中列名不重复可以省略“表名.”部分
  • 如果表的名称太长,可以在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

练习

  • 查询学生的姓名、平均分

select students.sname,avg(scores.score)

from scores

inner join students on scores.stuid=students.id

group by students.sname;

  • 查询男生的姓名、总分

select students.sname,avg(scores.score)

from scores

inner join students on scores.stuid=students.id

where students.gender=1

group by students.sname;

  • 查询科目的名称、平均分

select subjects.stitle,avg(scores.score)

from scores

inner join subjects on scores.subid=subjects.id

group by subjects.stitle;

  • 查询未删除科目的名称、最高分、平均分

select subjects.stitle,avg(scores.score),max(scores.score)

from scores

inner join subjects on scores.subid=subjects.id

where subjects.isdelete=0

group by subjects.stitle;

 

 

总结:

Select distinct *

From 表1 inner|left|right join 表2 on 表1与表二的关系

Where …

Group by ….. having…..

Order by …..  asc|desc

Limit start,count

 

 

 

视图

  • 对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情
  • 解决:定义视图
  • 视图本质就是对查询的一个封装
  • 定义视图

create view stuscore as

select students.*,scores.score from scores

inner join students on scores.stuid=students.id;

  • 视图的用途就是查询

select * from stuscore;

 

 

 

根据学生id分组,我们可以得到学生的姓名(如上图,分组之后不存在奇异),而不能更具学生的id确定学生的科目的成绩

自关联

一张表可以存大量的信息,如果只存几万条,是一种浪费。可以将三张不同的表建立咋一张表中,然后用自关联实现

从sql文件中导入数据

source areas.aql

查询一共有多少个省

    Select count(*) from areas where pid is null

查询省得名称为“山西省”的所有城市

事务

  • 当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回
  • 使用事务可以完成退回的功能,保证业务逻辑的正确性
  • 事务四大特性(简称ACID)
    • 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行
    • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
    • 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
    • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障
  • 要求:表的类型必须是innodb或bdb类型,才可以对此表使用事务
  • 查看表的创建语句
show create table students;
  • 修改表的类型
alter table '表名' engine=innodb;
  • 事务语句
开启begin;
提交commit;
回滚rollback;

示例1

  • 步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表
终端1:
select * from students;
------------------------
终端2:
begin;
insert into students(sname) values('张飞');
  • 步骤2
终端1:
select * from students;
  • 步骤3
终端2:
commit;
------------------------
终端1:
select * from students;

示例2

  • 步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表
终端1:
select * from students;
------------------------
终端2:
begin;
insert into students(sname) values('张飞');
  • 步骤2
终端1:
select * from students;
  • 步骤3
终端2:
rollback;
------------------------
终端1:
select * from students;

---------------------------------------------------------------------------------------------------------

索引

优化SQL语句时,先写定值,然后写定范围;少用or

查看索引

show index from 表名;

创建索引

create index indexName on mytable(字段(长度))

删除索引

drop index [indexName] on mytable;

猜你喜欢

转载自blog.csdn.net/qq_35810838/article/details/83474418
今日推荐