当前位置:首页 > IT技术 > 数据库 > 正文

一篇文章简述mysql
2021-09-17 19:49:17

::: hljs-center

1.SQL概述

:::

SQL用来和数据库打交道的,完成和数据库的通信,SQL是一套标准,但是每一个数据库都有自己觉得特性,别的数据库没有,当时用这个数据库特性相关的功能,这是SQL语句可能就不是标准了。

::: hljs-center

2.什么是数据库:

:::

数据库,通常是一个或者一组文件,保存了一些符合特定规格的数据,数据库对应的英语单词是DataBase,简称DB,数据库软件称为数据库管理系统个(DBMS),如Oracle,SQL Server,MySQL,,,,

::: hljs-center

3.mysql概述

:::

Mysql最初是由MySQL AB公司开发的一套关系型数据库管理系统,Mysql不仅是最流行的开源数据库,二期是业界成长最快的数据库,每天有超过7万次的下载量,其应用范围从大型企业到专有的嵌入应用系统

MySQL AB是由两个瑞典人和一个芬兰人在瑞典创办的,从08年初Sun Microsystems收购了MySQL AB公司,在09年Orcle收购了Sun公司,使Mysql并入Oracle的数据库产品线

::: hljs-center

增删改查:crud

:::

C:Create(增)
R:retrive(查:检索)
U:update(改)
D:Delete(删)

::: hljs-center

4.sql语句的分类:

:::

  1. DQL:数据查询语言(凡是带有select关键字的都是查询语句)
  2. DML:数据操作语言(凡是对表中数据进行增删改的都是DML)
    ::: hljs-center

::: hljs-left

insert delete update

:::

:::

insert增
delete删
update改

3.DDL:数据定义语言(凡是带有create drop alter都是DDL)DDL主要操作的是结构,不是数据

create :新建
drop:删
alter:改
这个增删改和DML不同,这个主要是对表结果进行操作

4.TCL:事物控制语言(包括事物提交commit,事物回滚:rollback)
5.DCL:数据控制语言(授权grant,撤销权限revoke)

::: hljs-center

5.mysql常用的命令

:::

::: hljs-center

  • 登陆命令:mysql -uroot -p 密码
  • 查看数据库:show databases;
  • 使用数据库:use mysql;
  • 查询数据库中的表 :show tables;
  • 查看表中的数据:select * from 表名字
  • 查看表的结构:desc 表名字
  • 查看mysql数据库的版本号:select version();
  • 查看当前使用的数据库:select database();
  • 终止命令的输入:ctlr +c
  • 注意:mysql是不见 “;” 不执行,“;”表示结束!!!
  • :::

::: hljs-center

6.简单查询

:::

1.查询一个字段 :

select 字段名 from 表名

其中要注意:
select 和from都是关键字,都是标识符
对于sql语句都是通用的,都是以‘;’结尾,素有sql语言不区分大小写

2.查询表的结构:

desc 表名;

3.查询一个字段:

select 字段一 from 表名;

4.查询两个或者多个字段,使用逗号隔开

select 字段一,字段二 from 表名;

5.查询所有字段:

5.1.把所有字段都写上
select a,b,c,d,e,f from 表名;
5.2.可以使用
selectl
from 表名;

6.给查询的列起别名(as关键字)

select 字段1,字段二 as字段二的别名 from 表名;
注意:只是更改了显示结果,原表没改的。select不会进行修改操作的,它只提供查询。

as关键字可以省略,用空格代替

select 字段1,字段二 空格 字段二的别名 from 表名;

假设起别名的时候,别名里面有空格怎么办???

解决方法:

select 字段1,字段二 空格(as) ‘字段二的别名’ from 表名;

如果别名是中文的话,就要用单引号括起来

select 字段一,字段二*12 as ‘中文别名’ from 表名;

7.字段可以使用数学表达式

比如计算字段二的12个月的工资情况。
select 字段一,字段二*12 as 字段二别名 from 表名;

::: hljs-center

7.条件查询where:(筛选)

:::

7.1不是将表中所有的数据都查找出来,是查询出来符合条件的
查询格式:

select 
字段1,字段2,字段3 
from 
表名 
where 条件;

7.2条件包括有:

= 等于

查询薪资等于800的姓名和编号
select name,num from 表名 where sal=800;

<> 或者 != 不等于

查询薪资不等于800的姓名和编号

select name,num from 表名 where sal!=800;

select name,num from 表名 where sal<>800;

< 小于

查询薪资小于2000的员工姓名和编号

select name.num from 表名 where sal < 2000;

<=小于等于

查询薪资小于等于2000的员工姓名和编号

select name,num from 表名 where sal <= 3000;

**> 大于

=大于等于
同理;**

between and 介于两者之间

查询薪资在2450到3000之间的员工信息,包括2450和3000

**第一种方法:>=  and <=**
select 
      name,num 
from 
      表名 
where
      sal >= 2450 and sal <= 3000 ;
**第二种方法:between  and**
select 
     name,num 
from 
      表名 
where 
      sal  between 2450 and 3000 ;

查询哪些员工的津贴补助为null

is null 为null
is not null 不为null
select name,num from 表名 where comm is null;

在数据库中,null不能使用=进行衡量,需要使用is null,null代表什么也没有,不是一个值,所以不能使用等号。

查询哪些员工的津贴补助不为null

select name,num from 表名 where comm is not null;

查询工作岗位为MANAGER并且工资大于2500的员工信息

and 并且

select name,num from 表名 where job='MANAGER' and sal > 2500;

or 或者

查询工作岗位是manage和工作岗位是SALESMAN的员工
select name,num,job from 表名 where job = 'manage' or job = 'SALESMAN';

in 包含,相当于多个or

查询工作岗位是manage和salesman的员工
select name,num,job from 表名 where job in ('manage','saleman');
eg:查询薪资是800和5000的员工信息

select name,num,sal from 表名 where sal = 800 or sal = 5000;

select name,num,sal from 表名 where sal in (800,5000);

not in 不在这几个值中的数据

select name,num,sal from 表名 where sal not in (800,3000,5000);

like 称为模糊查询,支持%或者下划线匹配

%:匹配任意多个字符
下划线:一个下划线只匹配一个字符

eg:找出名字中含有字母O 的

select name from 表名 where name like '%O%';

2.找出名字以T 结尾的

select name from 表名 where name like '%T';

找出第二个字母是A 的

select name from 表名 where name like '_A%';

找出以k开头的名字

select name from 表名 where name like ‘K%’;

找出第三个字母是R的名字

select name from 表名 where name like '__R%';

找出名字中有‘_’的 (转义字符)

select name form 表名 where name like '%_%';

::: hljs-center

7排序数据

:::

单一字段排序

排序采用order by 子句,order by后面跟上排序的字段,排序字段可以放多个,多个采用逗号分隔,order by默认采用升序,如果存在where子句,那么order by 必须到where语句的后面

按照薪水由小到大排序(系统默认是由小到大)
查询所有员工薪资排序

select name.num.sal from 表名 order by sal;

降序

select name.num.sal from 表名 order by sal desc;

两个或者两个以上的字段排序

薪资一样的话,就安装员工的姓名排序(升序)

select
    name,num
from
    表名
order by
     sal asc,name asc;

sal在前,起主导,只有sal相等的时候,才会考虑name.

根据字段的位置可以进行排序

按照查询结果的第二列sal进行排序。
select name.num,sal from 表名 order by 2;

eg:找出工资在1250到3000之间的员工信息,要求按照薪资降序排列

select name,num,sal from 表名 where sal between 1250 and 3000 order by sal desc;

::: hljs-center

8.数据处理函数

:::

数据处理函数又被称为单行处理函数,
单行处理函数:一个输入对应一个输出
多行处理函数:多个输入对于一个输出

单行处理函数常见的有:

::: hljs-center

  • Lower 转换小写
  • upper 转换大写
  • substr取子串(截取的字符串,起始下标,截取的长度)注意:起始下标从1开始
  • concat 字符串拼接
  • length 取长度
  • trim 去空格
  • str_to date 将字符串转换成日期
  • date_format 格式化日期
  • format 设置千分位
  • round 四舍五入
  • rand() 生成随机数
  • Ifnull 可以将null转换成一个具体值
  • case..when..than..when..then..else..end 当什么时候怎么做,其他时候怎么做。

:::

eg:lower例子

select lower(name) from 表名;

eg:upper例子

select upper(name) from 表名;

eg:找出员工名字第一个字母是A的员工信息

第一种方式:
select name,num from 表名  where name like 'A%';
第二种方式:
select name,num from  表名 where substr(name,1,1) = 'A';

eg:concat字符串拼接

select concat(name,num) from 表名;

eg:length取字符串长度

select length(name) as namelength from 表名;

eg:trim 去空格

select * from 表名 where name = trim (' hahahah');

eg:round 四舍五入

保留整数位:
select round(1234.56,0) from 表名;
保留一位小数:
select round(1234.56,1) from 表名;
精确到十分位:
select round(1234.56,-1) from 表名;

eg:生成随机数

select rand() from 表名;
100以内的随机数:

select round(rand()*100,0) from 表名;
image.png

ifnull 是空处理函数,在所有数据库当只当中,只要有null参与的运算,最终结果都是null;**
select name, sal+comm from 表名;**
image.png

*select name,(sal+comm)12 from 表名; 这是错误的做法
ifnull(数据,被当做哪个值),当补助为null的时候,把补助当做0 来计算。**

select name,(sal+ifnull(comm,0))*12 from 表名;
image.png

eg:当员工的工作岗位是manage的时候,工资上涨10%,当工作岗位是salesman的时候,公司上调50%

select name,job,sal as oldsal(case job when 'manage' than sal81.1 when 'saleman' than sal*1.5 else sal end) as newsal from 表名;
image.png

::: hljs-center

9.分组函数(多行处理函数)

:::

多行处理函数的特点:输入多行,最终输出一行
::: hljs-center
#### 5个分组函数

  • count 计数
  • sun 求和
  • max 最大值
  • min 最小值
  • avg 平均值

:::

eg:计算出最高工资

select max(sal) from 表名;
image.png
eg:计算出最低工资
select min(sal) from 表名;
image.png
eg:计算出员工的全体总工资
select sum(sal) from 表名;
image.png
eg:计算出全体员工的平均工资:
select avg(sal) from 表名;
image.png
eg:计算出这家公司有多少人
select count(name) from 表名;
image.png

分组函数在使用的时候需要注意哪些?

注意事项1.分组函数自动忽略null
image.png
*2注意事项二.eg:count()和count()的区别是什么?*
select coutn(
) from 表名;
image.png

selet count(comm) from 表名;
image.png

count(*):表示统计表中的总行数,(只要有一行数据,count++)
count(comm) :表示统计该字段下所有部位NULL的元素的总数。

注意事项三:所有的分组函数可以组合起来一起用

select sum(sal),min(sal),max(sal),avg(sal),count(*) from 表名;
image.png
::: hljs-center

10.分组查询

:::

分组查询:在实际的应用各种,可能哟这样的需求,先进行分组,对每一组的数据进行操作,这个时候,我们需要分组查询,如何来分组查询呢?

select
……
from
……
group by
……

将之前的关键字全部组合在一起,看一下他们的执行顺序

select 
……
from
……
where
……
group by
……
order by
……

执行顺序是

from------where-------group by -------select----order by

注意事项四:分组函数不能直接使用在where字句中

eg:找出比最低工资高的员工信息

select name,num from 表名 where sal > min(sal);

  • 这是错误滴,会报错,为什么呢???
  • 因为where在group by分组函数之前!!!!
    列如:找出每个工作岗位的工资和
    select job,sum(sal) from 表名 group by job;

image.png

  • 语句的执行顺序:先从表总查询数据
  • 2.根据job字段进行分组
  • 3.然后对每一组的数据进行sum(sal)
    重点结论:在一条select语句当中,如果有group by语句的话,select后面只能跟参加分组的字段,以及分组函数之外,其他的一律都不要加!!!!
    例如1:找出每个部门的最高薪资
    select 部门编号,max(sal) from 表名 group by 部门编号;

image.png
例题2:找出每个部门,不同工作岗位的最高薪资

select 工作岗位,部门, max(sal) from 表名 group by 部门,工作岗位;
image.png

例题三:使用having可以对分完组之后的数据进一步过滤,having必须和group by联合使用,
找出每个部门的最高薪资,要求显示最高薪资大于3000?

select 部门,max(sal) from 表名 group by 部门 having max(sal) > 3000;

方法二:先筛选出>3000过滤掉,然后在分组,在进行查询。

select 部门,max(sal) from 表名 where sal> 3000 group by 部门;

image.png

例题四:where没有办法的

找出每个部门的平均薪资,要求显示平均薪资高于2500的

select 部门 avg(sal) from 表格 group by 部门 having avg (sal)>2500;

select 部门 avg(sal) from 表格 where avg(sal)>2500 group by 部门 ;

这是错误的,因为因为,分组是在where之后执行的,而avg(sal)是分组函数。所以在这里只能使用having。

例题五:找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除开manage之外,要求按照平均薪资降序排序

select 岗位,avg(sal) from 表名 where job != 'manage' group by 岗位 having avg(sal) > 1500 order by avg(sal) desc;

image.png

把查询结果去除重复记录(distinct)

select job from 表名
image.png
select distinct job from 表名
image.png

distinct出现在两个字段之前,表示,这两个字段联合起来去重。

select distinct job,deptno from 表名;
image.png
例如:统计一下工作岗位的数量?
select count(dostomct job) from 表名

::: hljs-center

11.连接查询

:::

连接查询的概念:

从一张表中淡出查询,称为单标查询
多张表联合起来查询数据,被称为连接查询。

连接查询的分类:

1.根据语法的年代分类
SQL92:1992年出现的语法
SQL99:1999年出现的语法

2.根据表连接查询的方式分类:

内连接:

  1. 等值连接
  2. 非等值连接
  3. 自连接
    外连接:
  4. 左外连接:
  5. 右外连接:
    全连接

    注意:当两张表进行连接查询的时候,没有任何条件的限制会发生什么现象???

    笛卡尔积现象,它是一个数学现象。
    避免笛卡尔积现象!!!
    连接时加条件,满足这个条件的记录筛选出来,但是匹配次数是没有减少的,只不过把条件符合的筛选出来

    select 
    name,num
    from 
    表一,表二
    where
    表一.编号 = 表二.编号;

    image.png

提高效率,可以给表起别名

image.png

我们来看一下92语法和99语法的语法格式
比如,显示员工属于哪个部门,并且显示出员工和部门信息
SQL92

select 
表一别名.姓名,表二别名.部门 
from 表一 别名 ,表二 别名
where 
表一别名.部门编号 = 表二别名.部门编号;

SQL99

select 
表一别名.姓名,表二别名.部门 
from 
表一 别名 join 表二 别名
 on
表一别名.部门编号 = 表二别名.部门编号;
……
where 筛选条件

以上可以看出,sql92的缺点,结果不清晰,表的连接条件,和后期进一步筛选的条件都放到where中

sql99的优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,可以在语句后面加where,

内连接之等值连接(inner)

select 
   e.ename,d,dname
from
   emp e
inner join
   emp b
on
  e.deptno = d.deptno;

内连接之非等值连接

条件不是一个等量关系,称为非等值连接。
eg:找出每个员工的薪资等级,要求显示员工名,薪资,薪资等级。

select
    a.ename,a,sal,s.grade
from
    emp a
inner join
    salgrade s
on 
   a.sal between s.losal and s.hisal;

内连接之自连接

eg:查询员工的上级领导,要求显示员工名和对应的领导名
image.png
技巧:一张表看成两张表,

select 
a.ename as ‘员工名’,b.ename '领导名' 
from
emp a
join
emp b
on a.mgr = b.empno;

外连接

外连接(右外连接right)

select 
e.ename, d.dname
from
 emp e right join dept d
on
e.deptno = d.deptno;

外连接(左外连接 left)

 select 
e.name , d.name
from
dept d left join emp e
on 
e.deptno = d.deptno;

right 代表join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表,在外连接当中个,两张表连接,产生了主次关系

带有right的是右连接,
带有left的是左连接
任何一个右或者左连接都有他们左或者右的写法。
//outer 可以省略


select 
e.name , d.name
from
dept d left outer join emp e
on 
e.deptno = d.deptno;
**eg:查询每个员工的上级领导,要求显示所有员工的名字和领导名。**

select
a.ename,b.ename
from
emp a left join emp b
on
a.mgr = b.empno;

![image.png](https://s2.51cto.com/images/20210914/1631597445368174.png)

#### 多张表怎么连接

select
……
from
a
join
b
on
a和b的条件
join
c
on
a和c的条件
right join
d
on
a和d的条件


**一条sal语句中,内连接和外连接都能够混合使用,**

> eg:找出每个员工的部门名称,以及工资等级,要求显示员工名 工资 部门名 薪资等级

select
e.ename,e.sal,d.dname,s.grade
from
emp e
join
dept d
on
e.deptno = d.deptno;
join
salgrade s
on
e.sal between s.losal and s.hisal;


::: hljs-center

## 12.子查询

:::

#### 什么是子查询:
> select 语句中嵌套了select语句,被嵌套的select语句称为子查询
#### 子查询都可以出现在哪里呢?

select
……(select)
from
……(select)
where
……(select)
……

#### where字句中的子查询
> eg:找出比最低公司高的员工姓名和工资

select
ename,sal
from
emp
where
sal>(select min(sal) from emp);

#### from字句中的子查询
**from后面的子查询,可以把子查询中的结果当做一张临时表。**
eg:找出每个岗位的平均工资的薪资等级
> 每个岗位的平均工资:
select job,avga(sal) from emp group by job;
等级:

select
t.*,s.grand
from
(select job,avga(sal) as sal from emp group by job) t
join
salgrade s
on
t.sal between s.losal and s.hisal;

#### select出现的子查询
eg:找出每个员工的部门名称,要求显示员工名和部门名??

select
e.name e.deptno,
(select d.dname from dept d where
e.deptno = d.deptno) as dname
from emp e;


 ![image.png](https://s2.51cto.com/images/20210914/1631600860120199.png)

## union合并查询结果
> eg:查询工作岗位是manage和saleman的员工

select
ename,jog
from
emp
where
job='manage'or job='saleman';

union的使用
select ename,job from emp where job = 'manage';
union
select ename,job from emp where job = 'saleman';
union的优点:
> union的效率高一些,对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,但是union可以减少匹配的次数,在减少匹配次数的情况下,还可以完成两个结果的拼接

**注:union使用的注意事项:
union在进行结果集合并的时候,要求结果集的列数要想同!!!**

select ename from emp where job = 'manage';
union
select ename,job from emp where job = 'saleman';


**这样就是错误的**

::: hljs-center

## 14.limit分页查询

:::

> limit:显示结果集的一部分数据。
分页的作用:提高用户的体验,因为一次全部都查出来,用户体验差,可以翻页查看。

limit的使用:
eg:安装薪资降序,取出排序在前五名的员工

select
ename,sal
from
emp
order by
sal desc
limit 5;

**完整写法:**
limit的用法,后面可以跟两个数字,
limit startIndex (起始下标,从0开始), length(长度);
**缺省用法:**
limit 5;取前五

**在myql中,limit在order by之后执行。**
eg:取出工资排名在3-5名的员工

select
ename,sal
from
emp
order by
sal desc
limit 2,3;

> eg:取出工资5-9名的员工

select
ename,sal
from
emp
order by
sal desc
limit 4,5;

## 分页
**每页显示3条记录**
第一页:limit 0,3
第二页:limit 3,3
第三页:limit 6,3
第四页:limit 9,3
每页显示pagesize条记录,第pagenum页:
limit (页码-1)*pagesize,pagesize;

关于DQL语句总结:

select
……
from
……
where
……
group by
……
having
……
order by
……
limit


> 执行顺序:
from --- where---- group by ----having---- select---- order by ----limit

::: hljs-center

## 15.表的创建

:::

#### 1.建表的语法格式(DDL)
create table 表名 (
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型);
> 表名:建议以t_或者tbl_开始,可读性强,见名知意。
#### 2.数据类型有:
> varchar:可变长度的字符串,会根据实际的数据长度动态分配空间。
> char:定长字符串,不管实际数据长度,分配固定长度的空间去存储数据。使用不恰当,可能会导致空间的浪费。

int:数字中的整型,最长(11位)
bigint:数字中的长整型
float:单精度
double:双精度
date:短日期类型
datetime:长日期
clob:字符大对象,最多可以存储4G的字符串(255位)
比如:文章,说明,简介
blob:二进制大对象,专门用来存储图片,声音,视频,等流媒体数据。往BLOB类型字段上插入数据的时候,需要使用IO流

**
eg:创建一个学生表**
学号、姓名、性别、年龄、邮件地址
create table t_student (
num int,
name varchar(20),
sex char(1),
age int(3)
e-mail varchar(255));

**删除表**  drop table t_student;  //当这张表不存在的时候会报错
drop table if exists t_student ; //当这张表存在的时候删除
![image.png](https://s2.51cto.com/images/20210915/1631689867131213.png)

#### 4.插入数据:insert(DML)
语法格式
insert into 表名 (字段名1,字段名2,字段名3,……) values(值1,值2,值3,……);
注意:字段名和值要一一对应,数据类型要对应,
eg:

mysql> insert into t_student (no,name,age,sex,email) values (1,'张三',20,'m','zhangsan@qq.com');

![image.png](https://s2.51cto.com/images/20210915/1631690853156958.png)

**注意:前民的字段可以省略,后面的值必须要一一对应写上,!!**

#### 5.格式化数字:format(数字,‘格式’)

#### str_to_date 将字符串转换为日期类型
> 语法格式:str_to_date(‘字符串日期’,‘日期格式’)

> mysql的日期格式有:%Y/%m/%d/%h/%i/%s

![image.png](https://s2.51cto.com/images/20210915/1631693743713591.png)

#### date format 将日期类型转换成特定格式
**date format(日期类型数据,‘日期格式’)**
> 它会自动将数据库中的date类型转换成varchar类型,并且采用的格式是mysql的默认的日期格式。

![image.png](https://s2.51cto.com/images/20210915/1631694194875513.png)

#### date和datetime两个类型的区别

> date:是短日期,只包括年月日信息
datetime长日期,包括年月日时分秒信息

![image.png](https://s2.51cto.com/images/20210915/1631694780884609.png)

#### now()获取系统当前时间
![image.png](https://s2.51cto.com/images/20210915/1631694944195268.png)

## 修改update(DML)
语法格式:
> update 表名 set 字段名1=值1字段名2=值2,字段名3=值三,…… where 条件;
注意:如果不加where条件,会导致所有的数据全部更新!!!!

![image.png](https://s2.51cto.com/images/20210915/1631695512960181.png)

## 删除数据delete(DML)
delect from 表名 where 条件
注意:没有条件,整张表的数据都会删除。
![image.png](https://s2.51cto.com/images/20210915/1631695817841801.png)

![image.png](https://s2.51cto.com/images/20210915/1631695865318492.png)
**注意:delete删除之后可以回滚数据,可以恢复数据,数据在硬盘上的真实存储空间不会被释放,缺点是:删除效率比较低,**
**truncate:语句删除效率比较高,表被一次性清理了,不能恢复。
**
> truncate table表名;
![image.png](https://s2.51cto.com/images/20210915/1631699684540977.png)
#### insert可以一次性插入多条记录
语法格式:
> insert into t_time (字段名1,字段名2,字段名3) values(值1,值二,值三),(值1,值二,值三);

![image.png](https://s2.51cto.com/images/20210915/1631698676167062.png)

#### 快速创建表
语法格式
**create table 表名 as select * from 表二;**
> 原理:将一个查询结果当做一张表新建
这个可以完成表的快速复制
表创建出来,同时表中的数据也存在了
![image.png](https://s2.51cto.com/images/20210915/1631698912196536.png)
#### 表结构的增删改
alter(修改)
create(创建)
drop(删除)
> 1.在实际的开发中,需求一旦确定设计好之后,很少进行表结构的修改,添加字段,删除字段,修改字段等等。

因为开发进行中,修改表结构成本比较高,

::: hljs-center

## 16.约束

:::

约束:约束字段
#### 什么是约束????
> 约束(constraint),在创建表的时候,给表中的字段加一些约束,来保证表中数据的完整性和有效性。

#### 约束包括有:
> 非空约束:not null
唯一性约束:unique
主键约束:primary key
外键约束:foreign key
检查约束:check

#### 1.非空约束:not null;
它约束的字段不能为null;
![image.png](https://s2.51cto.com/images/20210916/1631760605825609.png)
#### 2.唯一性约束(unique)
> 唯一性约束unique约束的字段不能重复,但是可以为空

![image.png](https://s2.51cto.com/images/20210916/1631761607533434.png)

![image.png](https://s2.51cto.com/images/20210916/1631761626389133.png)

![image.png](https://s2.51cto.com/images/20210916/1631761644954074.png)
 #### 表级约束
> 什么时候使用表级约束呢?
需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束,not null 没有表级约束语法,unique有。
![image.png](https://s2.51cto.com/images/20210916/1631764983804028.png)
![image.png](https://s2.51cto.com/images/20210916/1631765000220796.png)
![image.png](https://s2.51cto.com/images/20210916/1631765014828027.png)

#### unique和not null 联用
在mysql中,如果一个字段同时被not null和unique同时约束的时候,该字段自动称为主键字段。

![image.png](https://s2.51cto.com/images/20210916/1631765403266026.png)
#### 主键约束
#### 1.主键约束的相关术语
> 主键约束、主键字段、主键值
主键约束:就是一种约束
主键字段该字段上添加了主键约束,这样的字段叫做:主键字段
主键值:主键字段中的每一个值叫做主键值
#### 2.什么是主键,有什么用??
> 主键值是每一行记录的唯一标识
主键值是每一行记录的身份证号
注意:任何一张表都应该有逐渐,没有主键,表无效!!!!
主键的特征:not null + unique(主键值不能是null,也不能重复,要具有唯一性)相当于身份证号。
**如何给一张表添加主键约束**
列级约束:
![image.png](https://s2.51cto.com/images/20210916/1631766689918501.png)
表级约束:
![image.png](https://s2.51cto.com/images/20210916/1631766578261788.png)

多个字段联合起来添加一个主键约束,
![image.png](https://s2.51cto.com/images/20210916/1631766828647909.png)
#### 
外键约束
外键约束可以为NULL,外键约束引用的字段不一定是主键,但是至少具有unique约束。
![image.png](https://s2.51cto.com/images/20210916/1631775313493945.png)
::: hljs-center

## 17.存储引擎

:::

**什么存储引擎???**
> 指定不同的存储引擎,表的存储结构不一样。

如何给表指定存储引擎
**show create table t_student;**
在建表的时候可以在最后小括号的右边使用:
![image.png](https://s2.51cto.com/images/20210916/1631776328154697.png)
> ENGINE:来指定存储引擎
CHARSET:来指定这张表的字符编码方式
默认的存储引擎是InnoDB
默认的字符编码是UTF-8;

 ![image.png](https://s2.51cto.com/images/20210916/1631776462766902.png)

#### 查看mysql中支持得存储引擎
**mysql> show engines G**

::: hljs-center

## 18.事物

:::

> 一个事物其实就是一个完整的业务逻辑。只有dml语句才会哟事物有关,其他语句都和事物无!!!!
因为只有update insert delete 这三个语句是对数据表中的数据进行增删改的,只要是涉及到数据的增删改的那么久一定要考虑到安全问题,数据安全是第一位。

#### 什么是事务呢?
> 一个事物就是多条dml语句同时成功或者同时失败。

#### 事务是怎么做到多条dml语句同时成功和同时失败的呢?
> innoDB存储引擎:提供一组哟哪里记录事务性活动的日志文件。
在事务的执行过程中,每一条dml的操作都会记录到事务性活动的日志文件中,在事务的执行过程中,我们可以提交事务,也可以回滚事务。

提交事务:清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中,提交事务标志着,事务的结束,并且是一种全部成功的结束

回滚事务:将之前所有的dml操作全部撤销,并且清空事务性活动的日志文件,回滚事务标志着,事务的结束,并且是一种全部失败的结束

#### 事务的4个特性:
> 原子性:说明事务是最小的工作单元,不可再分
一致性:所有事务要求,在同一个事务当中,多有操作必须同时成功,或者同时失败,
隔离性:A事务和B事物之间具有一定的隔离,像教室一样,教室的那道墙就是隔离性,
持久性:事物最终结束的一个保障,事物提交,就相当于将没有保存到硬盘上的数据保存到硬盘上。

#### 事物的隔离性:
**1.读未提交:read uncommitted(最低的隔离级别)(没有提交就已经读到了)**
什么是读未提交:
事物A可以读取到事物B未提交的数据
这种隔离级别存在的问题就是:
脏读现象:(Dirty Read)
我们称为读到了脏数据,这种隔离级别一般都是理论上的,大多数的数据库隔离级别都是二挡起步!!!

#### 2. 读已提交:read committed(提交之后才能读到)
**什么是读已提交:**
事物A只能读取到事物B已经提交了的数据
**这种隔离级别解决了什么问题?**
解决了脏读现象
**这种隔离级别存在什么问题?**
不可重复读取数据
**什么是不可重复读取数据呢?**
在事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次在读取的时候,读到的数据是4条,4不等于3,称为不可重复读取,
> 这种隔离级别是比较真实的数据,每一次读到的数据是绝对的真实,oracle默认数据库的隔离级别是:read committed

#### 3.可重复读(提交之后也读不到,永远读取的都是刚开始事务)

**什么是可重复读取??**
事务A开启之后,不管是多久,每一次在事务A中读取到的数据都是一致的,即使事务B将数据已经修改,并且提交了,事务A中
读取到的数据还是没有发生改变,这就是可重复读。
**可重复读解决了什么问题?**
解决了不可重复读取数据
**可重复读存在的问题是什么?**
可能会出现幻影读
**每一次读取到的数据都是幻象,不够真实,**

#### 4.序列化/串行化:selializable(最高的隔离级别)
> 这是最高隔离级别,效率最低,解决了所有的问题,这种隔离级别表示事务排队,不能并发,每一次读取到的 **数据都是最真实的,并且效率是最低的**
**eg:使用read uncommitted 读未提交**

![image.png](https://s2.51cto.com/images/20210916/1631789189732327.png)
![image.png](https://s2.51cto.com/images/20210916/1631789208526989.png)
![image.png](https://s2.51cto.com/images/20210916/1631789229387351.png)
![image.png](https://s2.51cto.com/images/20210916/1631789251261040.png)

::: hljs-center

## 19.索引

:::

#### 什么是索引:
> 索引在数据库表的字段上添加,为了提高检索查询效率存在的一种机制
,一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引,索引相当于一本书的目录,是为了缩小扫描范围而存在的机制。

#### 对于一本字典来说,查找某个汉子有两种方式:
> 1.一页一页挨着找,知道找到位置,这种查找方式属于字典扫描
2.第二种方式,先通过目录去定位一个大概的位置,然后直接定位到这个位置,做局域性扫描,缩小扫描的范围,快速的插座,这种查找方式属于通过索引检索,效率较高。

![image.png](https://s2.51cto.com/images/20210917/1631866851282560.png)
> 如果name字段上没有没有添加索引,或者说没有给name字段创建索引,mysql会进行全扫描,会将name字段上的每一个值都比对一遍,效率比较低,

**mysql在查询方面主要就是两种方式:1.全表扫描,2.添加索引(缩小扫描范围)。**

遵循左小右大原则存放,采用中序遍历取数据
我们来看索引的实现原理把!!!!

![image.png](https://s2.51cto.com/images/20210917/1631867336701148.png)
在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在myisam存储引擎中,索引存储在一个myi文件中,在innoDB存储引擎中索引存储在一个逻辑名称叫做tablespace当中,在memory存储引擎中索引被存储在内存当中,不管索引存储在哪里,索引在mysql当中都是一个树的形式存在(自平衡二叉树:B-Tree).
![image.png](https://s2.51cto.com/images/20210917/1631867892779421.png)

![image.png](https://s2.51cto.com/images/20210917/1631867968441194.png)

#### 在mysql当中,主键上,以及unique字段上都会自动添加索引
**什么条件下,我们会考虑给字段添加索引???**
> 条件1:数据量庞大
条件二:该字段经常出现在where后面,以条件的形式存在,这个字段经常被扫描
条件三:该字段很少dml操作,因为dml之后,索引需要重新排序。
#### 索引的创建 删除 查看
创建索引:

![image.png](https://s2.51cto.com/images/20210917/1631868555405150.png)

![image.png](https://s2.51cto.com/images/20210917/1631868569211908.png)

![image.png](https://s2.51cto.com/images/20210917/1631868881622941.png)

![image.png](https://s2.51cto.com/images/20210917/1631868891587082.png)
#### 索引失效
第一种情况
![image.png](https://s2.51cto.com/images/20210917/1631870496464234.png)

第二种情况
![image.png](https://s2.51cto.com/images/20210917/1631870513913629.png)

第三种情况

![image.png](https://s2.51cto.com/images/20210917/1631870529827712.png)

第四种情况

![image.png](https://s2.51cto.com/images/20210917/1631870546263858.png)

第五种情况:
![image.png](https://s2.51cto.com/images/20210917/1631870575754443.png)
#### 索引在数据库中的分类:
> 单一索引:一个字段上添加索引
复合索引:两个字段或者更多的字段上添加索引
主键索引:主键上添加索引
唯一性索引:具有unique约束的字段上添加索引。

越唯一,效率越高!!!!

::: hljs-center

## 20.视图

:::

#### 1.什么是视图:
> view:站在不同的角度去看待同一份数据,视图是用来简化sql语句的。
#### 2.创建视图:
create view  视图名字 as select * from emp;

mysql> create view dept_view as select * from dept2;
Query OK, 0 rows affected (0.01 sec)


#### 3.删除视图:
drop view  视图名

mysql> drop view dept_view;
Query OK, 0 rows affected (0.03 sec)


注意:视图as后面必须是DQL语句

#### 4.用视图做什么???
> 我们对视图对象进行增删改查,会导致原表被操作,

![image.png](https://s2.51cto.com/images/20210917/1631871159192807.png)

视图更新
**mysql> update dept_view set dname = 'xiejaingmei' where deptno = 60;**
![image.png](https://s2.51cto.com/images/20210917/1631871409896526.png)
假设有一条非常复杂的sql语句,而这条sql语句需要在不同的位置上反复使用,每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办,可以把这条复杂的sql语句以视图对象的形式新建。
![image.png](https://s2.51cto.com/images/20210917/1631871545123313.png)

::: hljs-center

## 21.DBA常用命令

:::
数据备份
#### 数据导出:在cmd命令行执行:
> mysqldump 库名 >D:位置.sql -uroot -p密码;

mysqldump 库名 表名 >D:位置.sql -uroot -p密码;

![image.png](https://s2.51cto.com/images/20210917/1631872640451661.png)

#### 数据导入:
> 进入数据库
mysql -u root -p 密码
创建库
create database xjm;
使用数据库
use xjm;
初始化数据库
source D:xjm.sal;

::: hljs-center

## 22.数据库设计的三范式

:::

数据库表的设计依据,教你怎么进行数据库表的设计
> 第一范式:
要求一张表必须有主键,没一个字段原子性不可再分
第二范式:
建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖。
第三范式:完全建立在第二范式基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖。
按照以上的范式进行,可以避免表中数据的冗余,避免空间的浪费

**第一范式:最核心,最重要的范式,所有表都需要满足,必须要有主键,并且每一个字段都是原子性不可再分。**

![image.png](https://s2.51cto.com/images/20210917/1631873050247090.png)

第二范式,建立在第一范式基础之上,要求所有非主键字段,完全依赖于主键,不要产生部分依赖

![image.png](https://s2.51cto.com/images/20210917/1631873549520370.png)

![image.png](https://s2.51cto.com/images/20210917/1631873582467985.png)
![image.png](https://s2.51cto.com/images/20210917/1631873518807179.png)
第三范式,建立在第二范式的基础上,要求所有非主键字段完全依赖主键,不要产生传递依赖
![image.png](https://s2.51cto.com/images/20210917/1631873762217185.png)
![image.png](https://s2.51cto.com/images/20210917/1631873858384421.png)

一个班级对应多个学生

## 多对多:三张表,关系表,两个外键
一对多:二张表 多的表加外键
一对一:在实际开发中,可能存在一张表字段太多,太庞大,这个时候要拆分表。
#### 总结表的设计
> 一对一:外键唯一(fk+unique)
一对多:二张表 多的表加外键
多对多:三张表,关系表,两个外键

本文摘自 :https://blog.51cto.com/u

开通会员,享受整站包年服务立即开通 >