数据库mysql高级

Posted voong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库mysql高级相关的知识,希望对你有一定的参考价值。

简介

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

关系

  • 创建成绩表scores,结构如下
    • id
    • 学生
    • 科目
    • 成绩
  • 思考:学生列应该存什么信息呢?
  • 答:学生列的数据不是在这里新建的,而应该从学生表引用过来,关系也是一条数据;根据范式要求应该存储学生的编号,而不是学生的姓名等其它信息
  • 同理,科目表也是关系列,引用科目表中的数据
  •  

引用主键:把学生表的id引到成绩表。 一个学生对应多个成绩,学生和成绩是一对多,一个科目对应多个学生成绩,所以科目和成绩也是一对多(一对多就把关系字段存储在多的表中,多对对的话就新建一张表存关系)

  • 创建表的语句如下
create table scores(
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2)
);
decimal(4,1)一共4位数,小数占一位

   查看表scores的结构

  stuid=1的这个学生在subid=1的这个科目考了100分

外键

  • 思考:怎么保证关系列数据的有效性呢?任何整数都可以吗?(比如只有三个班级,但有个学生信息在四班就错了)
  • 答:必须是学生表中id列存在的数据,可以通过外键约束进行数据的有效性验证
  • 为stuid添加外键约束(stu id是关系字段,添加外键是为了保证stuid的有效性)
alter table scores add constraint stu_sco foreign key(stuid) references students(id);
  • 此时插入或者修改数据时,如果stuid的值在students表中不存在则会报错
  • 在创建表时可以直接创建约束
create table scores(
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) ); 
注:stuid指的是对这个表的哪个字段做外键,
reference后边跟的是引用哪个表的哪个字段(一般就是主键)

外键的级联操作

 

 把第一张表student中id=1的学生删了,那么在第二张表scores中所有stuid=1的学生都无效了,此时该怎么办?级联操作提供了四种方法

  • 在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常
  • 推荐使用逻辑删除,还可以解决这个问题
  • 可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作
  • 语法
alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;
  • 级联操作的类型包括:
    • restrict(限制):默认值,抛异常(报错)
    • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除(把stuid=1的行都物理删除)
    • set null:将外键设置为空(把stuid=1的行都设为空)
    • no action:什么都不做(你删你的,我啥都不做)

连接简介

先看个问题

  • 问:查询每个学生每个科目的分数
  • 这样不好看呀,中国人都是记名字,谁去记编号啊
  • 分析:学生姓名来源于students表,科目名称来源于subjects,分数来源于scores表,怎么将3个表放到一起查询,并将结果显示在同一个结果集中呢?
  • 答:当查询结果来源于多张表时,需要使用连接查询
  • 关键:找到表间的关系,当前的关系是
    • students表的id---scores表的stuid
    • subjects表的id---scores表的subid
  • 则上面问题的答案是:
select students.name,subjects.stitle,scores.score
from scores
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id;
join后边写表的名字,on后边写关系(scores和student的关系)
这样多好看呀!!
  • 结论:当需要对有关系的多张表进行查询时,需要使用连接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.name,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;
  • 查询男生的姓名、总分
select students.name,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
where students.gender=1
group by students.name;
  • 查询科目的名称、平均分
select subjects.title,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;



 

自关联:物理上是一张表,逻辑上是多(三)张表;连接成功就是一张大表(比如学生和成绩在一起的大表

本表当中的某个字段引用这个表当中的主键(这个表当中的外键引用这个表当中的主键),自关联查询必须起别名(如果都一样都是areas就没法区分谁是谁了)

    

   

    reference后边跟的是自己,表示自引用

创建表:

 

查看表:

  

  

把areas.sql文件放在桌面上,命令:退到桌面,再连接数据库,再showdatabases,show tables

 

 

 

 

把市过滤掉:

 

 

 

视图

  • 对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情
  • 解决:定义视图
  • 视图本质就是对查询的一个封装
  • 定义视图
create view stuscore as 
select students.*,scores.score from scores
inner join students on scores.stuid=students.id;
stuscore是创建的视图的名字,为了它不和表名冲突,一般这个名字以v开头,视图和表时放在一起的

 

    

  • 视图的用途就是查询
 select * from stuscore; 这一句就代表刚刚那一大坨代码,如果想修改这个视图用alter
 
 

事务

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

 

    表里有个数据叫1郭靖,比如说要做一个updat操作,首先执行begin把1郭靖这条数据锁起来,想删除修改这个数据都不行,然后在临时的一个表中把数据改成1小郭,再执行commit提交确定刚刚的更改,rollback放弃刚刚的操作(begin后边的      所有操作都放弃)还是原来的数据1郭靖(commit和roolback二选一,要么提交要么放弃)

示例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;

 

以上是关于数据库mysql高级的主要内容,如果未能解决你的问题,请参考以下文章

部分代码片段

Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrackonTriggeronInvalidate副作用的刷新时机`watch` pre)(代码片段

高级openg 混合,一个完整程序

从mysql的片段中加载ListView

连接MySQL出现错误:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)(代码片段

SQL笔记--MySQL高级操作