infinite-war'sBLOG
CARD
Mitchell
issue, func, flow, std, solve
30 | 15 | 22
SKIN
SETTINGS
Night Shift
Disable Canvas
简体中文
中文
|
English
|
日本語
PAGE CONTENT
MySQL80 操作要点笔记
2021-09-22
2021-09-22
6.9k
51 min.

# 前言

参考视频:BV1Vy4y1z7EX

CSDN: https://blog.csdn.net/INFINITE_WAR/article/details/120408155

一些频繁出现的用例名字: emp 员工信息表 dept 部门信息表 ename 员工名 job 工作 sal 工资 deptno 部门编号

# 一、开始

SQL现为手动模式(cmd操作,要管理员模式)

net start MySQL80  //打开MySQL80服务
net stop MySQL80   //关闭	

请添加图片描述 请添加图片描述 需要提前注册mysql账号

xxxx.sql 为sql脚本文件,里面编写了大量的sql语句,在mysql中使用命令‘source (文件路径)’ 即可执行脚本文件里的所有语句。

开始会有一个基础数据库databases,里面嵌套着其他数据库。

mysql> show databases;
+-----------------------------+
| Database                    |
+-----------------------------+
| first_database              |   //自己测试用的表在这里。也可以另行开辟
| information_schema          |
| mysql                       |
| performance_schema          |
| sakila                      |
| sys                         |
| world                       |
+-----------------------------+
7 rows in set (0.00 sec)

通过 ‘use (数据库名)’可以打开指定数据库,可以在该数据库中建立表并继续操作。

打开first_database后使用show tables 命令显示所有的表。

mysql> show tables;
+--------------------------+
| Tables_in_first_database |
+--------------------------+
| score                    |
| student                  |
| tab1                     |
+--------------------------+
3 rows in set (0.00 sec)

student的创建:

mysql> CREATE TABLE student ( -> id INT(10) NOT NULL UNIQUE PRIMARY KEY , -> name VARCHAR(20) NOT NULL , -> sex VARCHAR(4) , -> birth YEAR, -> department VARCHAR(20) , -> address VARCHAR(50) -> ); Query OK, 0 rows affected, 1 warning (0.07 sec)

score的创建: mysql> CREATE TABLE score ( -> id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT , -> stu_id INT(10) NOT NULL , -> c_name VARCHAR(20) , -> grade INT(10) -> );

# 二、基本命令

# part1

(命令不区分大小写)

exit//退出

(以下命令要分号结尾,否则会出现无限的“-->”符号让你输入)

show databases; //显示已有的数据库。 mysql默认自带了4个数据库。

use (数据库名); //表示正在使用对应的数据库

create database (数据库名); //建立一个新的数据库

show tables; //查看某个数据库下有哪些表

# part2

select version(); //查看当前mysql版本号

rowback //撤销一步

\c //强制停止当前语句(可以跳出“-->”死循环)

# 三、SQL语句分类

# DOL

数据库查询语言(凡是带有select关键字的都是查询语句)

select .....;

注:select本身是不会对原本的数据库进行修改操作的。

# DML

数据库操作语言(凡是对表当中的数据进行增删改的都是DML)

insert(增)

delete(删)

update(改)

注DML主要操作的是表中的数据

# DDL

数据定义语言(凡是带有create、drop、alter的都是DDL)

注:DDL主要操作的是表的结构,而不是表中的数据。

create:新建

drop:删除

alter:修改

# TCL

事务控制语言

commit; //事务提交

rollback; //事务回报

# DCL

数据控制语言

grant; //授权

revoke; //撤销权限

# 四、导入数据

mysql> source 路径+文件名

注:路径不能用中文

查看表中数据: select * from 表名;

查看表的结构:desc 表名; //<---desc是describe的缩写,可以用原词作命令

# 五、查询(单表查询part1)

# 1.查询一个字段

select 字段名 from 表名; //select 和from都是关键字,字段名和表名都是标识符

# 2.查询多个字段

select 字段名1,字段名2,....,字段名n from 表名;

# 3.查询所有字段

方法一,把所有字段都写上:

​ select 字段名1,字段名2,....,字段名n from 表名;

方法二,使用*: //缺点:效率低,可读性差

​ select * from 表名; //回想一下查看表中数据的命令

# 4.查询所有字段并去重

select distinct 字段名 from 表名 //distinct关键字必须出现在所有字段名之前

# 5.给查询的列起别名

select (字段名 as 自定义新字段名) from 表名;

//只是修改名字后显示出来,原本的数据库没有改变。

//若字段名有空格,要以 ‘新字段名’ 的形式写入命令(字符串统一使用单引号)。as可以用空格代替。

可以对字段使用数学表达式,例如:

select  name ,  score*12  from student;       //可以用  as  给score*12换名

会显示:

+----------------------+-----------------------+

​ name | score*12

+----------------------+-----------------------+

| ................. ....................... |

# 6.条件查询

# 6.1关系运算符

= 等于
<> 或 != 不等于
<、<=、>、>= 小(大)(等)于,
between (a) and (b) >=a && <=b
is null 为空
and
or
in 包含,相当于多个or
not
like 模糊查询,支持 % 或 下划线 匹配
% 匹配任意字符
下划线(_) 匹配一个字符

# 6.2 条件查询语法格式

(为了直观,句子将不写在一行里)

select 

      字段1,字段2,字段3  ......

from

      表名

where

​      条件;

# 6.3 比较不熟悉的关系运算符

# 6.3.1 in 的用法

例:筛选出工资为5000 或 6000 或 7000的所有员工

不用inselect     num , name , job  from  tab1 

​			where  wage=5000  or  wage=6000   or  wage=7000;

使用in: select     num , name , job  from  tab1 

​			where  wage  in  (5000,6000,7000);

# 6.3.2 like 的用法

例:

select  name  from  table  where   name  like   "%A%";

筛选出姓名中含有“A”的姓名。

其他例:


找出名字以T结尾的:

​		select  name  from  table  where   name  like   "%T";

找出名字以K开始的:

​		select  name  from  table  where   name  like   "K%";

找出第二个字母是A的:

​		select  name  from  table  where   name  like   "_A%";

找出第三个字母是R的:

​		select  name  from  table  where   name  like   "__R%";

从上例可以看出,所谓的模糊查找本质上和正则表达式匹配类似。

# 六、排序(单表查询part2)

# 1.语法

select 

​		字段名1,字段名2.......from

​		表名

​order by

​		指定字段名  ;    //==默认升序==

指定降序,则要写成 指定字段名 desc ;

指定升序,则要写成 指定字段名 asc ;

# 2.多字段排序


select 

​		字段名1,字段名2.......from

​		表名

​order by

​		指定字段名1   (指定顺序)  ,指定字段名2  (指定顺序),......

从左到右优先排序

# 3.根据字段位置排序

select    name   from   table   order  by    2

(指定字段名所在的列数,例句中指定第二列的字段) ;

# 4.综合案例

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


select  

​		ename ,sal

from

​		emp

where

​		sal  between  1250  and  3000

order by

​		sal  desc  ; 

语句执行顺序:

​ step1:from

​ step2:where

​ step3:select

​ step4:order by

# 七、数据处理函数(单表查询part3)

# 1.单行处理函数

特点:输入一行,输出一行。

lower/upper 转换成小(大)写
substr 取子串
length 取长度
trim(字符串) 去空格
str_to_date 将字符串转换成日期
date_format 格式化日期
round(数值,保留几位小数(-1是保留到十位)) 四舍五入
rand() (直接使用会生成[0,1)的随机数) 生成随机数
ifnull(数据,该数据的null情况用什么值取代) 将null转换成一个具体值
concat(字符串1,字符串2) 连接两个字符串
用法:select    函数名(参数1,参数2......)   as   自定义列名     from   表名;

注:null加上数值的结果还是null,故要使用ifnull修改最初的null值。

分支处理(类似于编程里的if else语句):

例:当员工的工作岗位时MANAGER时,工资上调10%;当工作岗位时SALESMAN时,工资上调50%;其他不变。

select

​		ename , job ,==(case  job  when   'MANAGER'   then  sal * 1.1     when    'SALESMAN'    then   sal * 1.5  else sal  end )   as  newsal==from 

​		emp;

# 2.多行处理函数(分组函数)

特点:输入多行,输出一行。

count(字段名) 计数
sum(字段名) 求和
avg(字段名) 平均值
max(字段名) 最大值
min(字段名) 最小值

注:1.分组函数在使用的时候必须先进行分组,然后使用。

2.如果没有对数据进行分组,整张表默认为一组。

3.分组函数会自动处理null值。

4.count(具体字段):表示统计该字段下所有不为null的元素的个数。

count(*):统计表当中的总行数。

5.分组函数不能中介用在 where 语句中。

# 八、分组查询(单表查询part4)

实际需求:先分组,再对每一组的数据进行操作。

例:计算每个部门的工资和

计算每个工作岗位的平均薪资

找出每个工作岗位的最高薪资

# 语法

select             //==若有 group   by,则应该只能写group  by   后面跟着的字段名==,或分组函数.....

from.....

(where  .....)

group  by       //后面只能跟  参加分组的字段,以及分组函数

​		(字段名).....

(having......)    //作用和where 差不多,但是必须接在group  by后面

(order by .....)

执行顺序:

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

例:找出每个部门、不同岗位的最高薪资

select

​		deptno,job,max(sal)

from

​		emp

group by

​		deptno  ,  job;

综合案例:

找出每个岗位的平均薪资,要求平均薪资大于1500的,除MANAGER岗位之外,要求按照平均薪资降序排序。

select

​		job  ,  avg(sal)  as  avgsal

from

​		emp

where

​		job  !=  'MANAGER'

group by

​		job

havingavg(sal)  >  1500

order by

​		avgsal  desc;

# 九、连接查询

注:可以先去了解一下关系数据库的连接运算

连接查询的目的:多张表联合起来查询数据。

连接的底层原理是笛卡尔积。若连接查询不附带任何注释,则会返回一个数据库字段之间笛卡尔积的结果。

简单案例:查询每一个人所在的工作部门。

//SQL92的解法


select   

​		e.ename  ,  d.dname        //最好将字段所属的表名通过这种方式标出

from

​		emp  e,  dept  d            //表名空格后面为别名。

where

​	    emp.deptno  =  dept.deptno  ;          //表的连接条件,通过and可以写入进一步的过滤条件

# 9.1 内连接

# 9.1.1 等值连接

上例SQL99的语法


select

​		e.ename  ,  d.dname

from

​		emp e

join

​		dept d

on               //独立出来的连接条件

​		e.deptno  =  d.deptno ;

SQL92缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件都放在了where中。

SQL99的优点:表连接的条件是独立的,连接之后,若还要进一步筛选,再写where语句。

SQL99连接语法:

select......

from

​		a

join

​		b

on

​		a和b的连接条件

where

​		筛选条件

# 9.1.2非等值连接

where 下的筛选条件不是一个等量关系

# 9.1.3自连接

样例表:

员工编号 姓名 上司编号
7369 SMITH 7902
7499 ALLEN 7698
7521 WARD 7698
7566 JONES 7839<==
7654 MARTIN 7698
7698 BLAKE 7839<==
7782 CLARK 7839<==
7788 SCOTT 7566
7839<== KING NULL
7844 TURNER 7698
7876 ANAMS 7788
7900 JAMES 7698
7902 FORD 7566
7934 MILLER 7782

内连接用法:查询员工的上司,要求显示员工名和对应的领导名。

注:同一个表用两个名称


select

​		a.姓名   as  '员工名'  ,  b.姓名   as   ‘上司名’

from

​		emp  a

join 

​		emp  b

on

​		a.上司编号  =  b.员工编号

# 9.2 外连接

例:给定一个存储员工信息的表emp ,一个存储部门信息的表dept。

要求连接员工姓名与他对应的部门,并将空的部门也一起显示。(因为有可能有的部门的人都不在表emp中)

select             (右外连接或右链接) (emp  和  dept之间存在主次关系。dept为主)

​		e.ename , d.dname

from

​		emp  e    right  join  dept  d       //right 表示 右边的表中没有匹配成功的记录也要																																显示

//(左外连接)		dept   d   **left**    emp   e            这句话与上句话相同

//关键字right表示右边的表一定要全部显示出,left同理。

on

​		e.deptno = d.deptno  ;

# 9.3 多表连接

语法:


select.............

from

​		 a

join     b

on

​		 a 和 b 的连接条件

join     c

on

​		 a 和 c 的连接条件

。

。

。

join     n

on

​		 a  和  n  的连接条件  ;

注:内连接和外连接可以混合使用。

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


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  ;

# 9.4 union 关键字

数据量大的情况下union比普通连接效率高

前提:连接的两个表选出的列数相同

例:

select ename, job from  emp  where  job='MANAGER'

union

select  ename ,  job from emp  where  job='SALESMAN';

# 十、子查询

select语句中嵌套select语句,嵌入的select语句称为子查询

如:

select.....select.....

from.....select.....

where.....select.....

# 10.1 where中的子查询

例:找出比最低工资高的员工姓名和工资。

错误方法:

select:

​		ename  ,  sal

from

​		emp

where

​		sal > min(sal) ;           //此句错误,min这种多组函数使用前必须先分组。

思路:

//step1:查询最低工资

select    min(sal)   from   emp ;    //假设查出为800

//step2:找出大于最小工资的员工

select    ename , sal   from   emp   where   sal>800 ;

//step3:合并前两步

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

# 10.2 from中的子查询

这种子查询可以将子查询的查询结果当成一个临时表。(技巧)

例:找出每个岗位的平均工资的薪资等级。

思路:

//step1:找出每个岗位的平均工资(按照岗位分组求平均值)

select   job  ,  avg(sal)   from   emp    group   by   job;

//step2:第一步得到了临时表 t 。现有薪资评级表 salgrade。

t 和 salgrade 连接


select

​		t.* , s.grade

from

​		t

join

​		salgrade s

on

​		t.avg(sal)       between   s.losal   ans  s.hisal ;

//step3:合并前两步

select

​		t.* , s.grade

from(select  job , <u>avg(sal)  as  avgsal</u>  from  emp  group  by  job)  t

join

​		salgrade s

on<u>t.avgsal</u>       between   s.losal   ans  s.hisal ;

# 10.3 select中的子查询

例:找出每个员工的部门名称,要求显示员工名,部门名。


select

​		e.ename , (select  d.dname  from   dept  d    where    e.deptno = d.deptno) as 			dname

from

​		emp;

注:对于每一条记录,若子查询超过一条就会报错。

# 十一、分页查询

# 11.1 limit关键字

目的:将查询结果集的一部分取出来。(搜索引擎搜索结果的分页)

用法:

limit    startindex,length       //写在order  by  后面

例:按照薪资排序,取出排名前5的员工。

select  

​		ename , sal

from

​		emp

order by 

​		sal desc

limit    0,5        //也可以写成  limit   5。表中的记录从0开始。

# 11.2 分页

每页显示pageSize条记录

​ 第pageNo页:limit (pageNo - 1)* pageSize , pageSize

如: 第1页:limit 0,3 [0 1 2]

第2页:limit 3,3 [3 4 5]

第3页:limit 6,3 [6 7 8]

第4页:limit 9,3 [0 1 2]

# 十二、建表

创建表格式:create  table  表名(字段名1  数据类型,字段名2  数据类型,。。);

删除表格式:drop  table  if   exists    (要删除的表名) ;

添加记录:insert  into   表名  values(字段名和值一一对应)  ;

常见数据类型:varchar(动态分配字符串内存),char(静态分配),int,bigint,float,double,date(短日期),datetime(长日期),clob(字符大对象),blob(二进制大对象)

clob:可以存储最多4G 的大字符串(如文章)。

blob:存储图片、声音、视频等流媒体数据。需要使用IO流

# 12.1修改(update)

update  

​		表名  

set  		//修改具体值

​		字段名1=1,字段名2=2,。。。

where... ;//指定特定条件的记录,不写where默认修改所有记录

# 12.2删除记录delete(DML)

delete   from   表名   where  ......//不写where会删除所有数据

# 12.3插入多条记录

insert  into  表名(字段名1,字段名2。。。)   values

(元组一),

(元组二),

。。。,

(元组n);   //元组数据类型必须与第一行的字段名一一对应

# 12.4快捷命令

# 12.4.1 快速创建表

create    table   新表名   as   select   *  from   原表名;   //select语句可以按需求扩充内容(如where,order by等)

# 12.4.2 快速删除数据

truncate  table  表名 ;   //与‘delete   from   表名’     相同

truncate和delete的区别

truncate delete
删除效率相对比较高,表被依次截断,物理删除 表中的数据被删除了,但是删除的数据在硬盘上的真实存储空间不会被释放
缺点:不支持撤销操作 缺点:删除效率较低(一亿条记录时要1小时才能删完)
有点:快速(数据量非常大的时候推荐使用。一亿条记录是删除时间不到1秒) 优点:支持撤销操作
是DDL语句 是DML语句

# 十三、约束

目的:确保数据的完整性、有效性。

常见约束:非空约束(not null)、唯一性约束(unique)、主键约束(primary key ,PK)、外键约束(foreign key,FK)、检查约束(check)

# 13.1 非空约束

not null 约束的字段不能为NULL。

drop  table  if  exist  t_vip;

create  table  t_vip(

    id  int,

    name   carchar(255)   **not  null**

);

# 13.2 唯一性约束

unique约束的字段不能重复,但是可以为NULL。

使用例:

drop  table  if  exist  t_vip;

create  table  t_vip(

    id  int,

    name   carchar(255)   **unique**,            //该字段的内容不能重复

    email  varchar(255)

);

推广:不同字段在特定条件下可以联合设置为唯一性约束。(如:两个人姓名相同,但是电话号码不同。或者说一个人有多个电话号码记录)

drop  table  if  exist  t_vip;

create  table  t_vip(

	id  int,

	name   carchar(255) ,   

	email  varchar(255)unique(name , email)      //联合唯一性

);

下例为unique和not null 联合使用

drop  table  if  exist  t_vip;

create  table  t_vip(

	id  int,

	name   carchar(255)   **not  null  unique**,   //该字段的内容不能重复也不能为空

	email  varchar(255)

);

这种联合的效果就是主键约束,也就是说,可以直接用PK约束实现前两种约束的联合。

# 13.3 主键约束

术语:主键约束、主键字段、主键值

主键例:学号、身份证......

建议设为主键的类型:int、bigint、char等。(varchar不建议)

注:一个表中只能设置一个主键

特征:not null 、 unique

# 13.3.1 单一主键和复合主键(分类一)

使用例:

drop  table  if  exist  t_vip;

create  table  t_vip(

	id  int,

	name   carchar(255)   **primary  key **   , 

	email  varchar(255)

);

复合主键使用例:

drop  table  if  exist  t_vip;

create  table  t_vip(

	id  int,

	name   carchar(255) ,    

	email  varchar(255)primary  key(id,name)     //号码、姓名同时相同时才算重复。

);

# 13.3.2 自然主键和业务主键(分类二)

自然主键:主键值是一个自然数,和业务无关。<==使用较多

业务主键:主键值和业务关联,例如银行卡号。

自动维护主键值使用例:

drop  table  if  exist  t_vip;

create  table  t_vip(

	id  int    **primary  key   auto_increment**  

	name   carchar(255) ,

	email  varchar(255)

);

# 13.4 外键约束

相关术语:外键约束、外键字段(添加了外键约束的字段)、外键值(可以为null)。

应用场景:处理学生和班级时,应当把班级额外设置为一个表再对学生进行外键约束。(t_class , t_student)

t_class

classno classname
100 一班
101 二班

t_student

no name cno
1 jack 100
2 lucy 100
3 lilei 100
4 bob 100
5 ben 101
6 alice 101
7 alex 100
8 zhangsan 101

t_class 是父表,t_student是子表。

删除表的顺序:先删子,再删父。

创建表的顺序:先创建父,再创建子。

删除数据的顺序:先删子,再删父。

插入数据的顺序:先插入父,再插入子。

drop  table  if  exist   t_student;

drop  table  if  exist   t_class;



create  table  t_class(

​		classno  int  primary  key,

​		classname   varchar(255)

)



create  table  t_student(no  int  primary   key  auto_increment,

​		name  varchar(255),

​		cno  int,**foreign  key(cno)  references  t_class(classno)**  

)

# 十四、存储引擎

注:存储引擎是mysql的特有术语。

存储引擎即数据内容的存储方式,如:ANSI,UTF-8等。

查看mysql支持哪些存储引擎:show engines

展示新建表的存储引擎:show create table (表名)

指定引擎使用例:

create  table  t_product(

​		id  int  primary  key ,

​		name  varchar(255)

)engine=InnoDB  default  charset=utf8;

# 14.1 My ISAM存储引擎

使用三个文件表示每一个表:

​ 格式文件:存储表结构的定义 xxx.frm

​ 数据文件:存储表行的内容 xxx.MYD

​ 索引(目录)文件:存储表上索引 xxx.MYI

特点:可以转换为压缩、只读表来节省空间。

# 14.2 InnoDB存储引擎(默认引擎)

InnoDB支持事务,支持数据库崩溃后自动恢复机制

特点:非常安全,效率不高,不能压缩或转换为只读。

InnoDB管理的表的特征:

​ 每个InnoDB表再数据库目录中以 .frm 格式文件表示

​ InnoDB表空间tablespace被用于存储表的内容

​ 提供一组用来记录事务性活动的日志文件

​ 用COMMIT(提交),SAVEPOINT以及ROOLBACK支持事务处理

​ 提供全ACID兼容

​ 在mysql服务器崩溃后会自动回复

​ 多版本(MVCC)和行级锁定

​ 支持外键及引用的完整性,包括级联删除和更新

# 14.3 MEMORY存储引擎

数据存储在内存中,且行的长度固定

特点:查询速度快,不安全

MEMORY管理的表的特征:

​ 在数据库目录内,每个表均以 .frm 格式的文件表示。

​ 表数据及索引被存储在内存中

​ 表级锁机制

​ 不能包含TEXT 或 BLOB字段

# 十五、事务(DML语句)

定义:一个事务是一个完整的业务逻辑。

事务特性:

​ A(原子性):事务是最小的工作单元,不可再分。

​ C(一致性):一系列操作必须同时成功或同时失败。

​ I(隔离性):不同事务之间不影响

​ D(持久性):保存内容,提供保障。

完整的业务逻辑例:

​ 业务:A转账10000元给B

​ 步骤:A的账户-10000,B的账户+10000。

这一系列操作必须同时成功或同时失败。

即,一个事务就是一系列的DML语句。

注:InnoDB会提供一组用来记录事务性活动的日志文件

如:

事务开启,写入日志

insert...

insert...

.

.

.

事务结束,写入日志          //提交事务



提交事务:commit ;语句

回滚事务:rollback ;语句     //回到上一次提交的位置

关闭自动提交操作:start    transaction

# 15.1 事务隔离

级别:

​ 读未提交:read uncommitted(不提交也读到) 最低级

​ 事务A读到事务B未提交的数据。易产生脏数据(Dirty Read)。

​ 读已提交:read committed (提交了才能读到)

​ 事务A只能读到事务B提交之后的数据。

​ 不可重复读数据。如:事务开启后,第一次读到的数据是3条,当前事务还没有结束,可能第二次在读取的时候,读到的数据是4条,3不等于4。

​ 可重复读:repeatable read (提交了也读不到) //mysql默认级别

​ 读取的是数据的幻象,读到的都是事务刚开始时的数据。

​ 序列化:serializable 最高级

​ 效率低,但是解决了所有的问题

​ 这种级别表示事务排队,不能并发。

# 十六、索引

类似于书的目录,提高搜索效率。

mysql查询的方式:1.全表扫描。2.根据索引检索

索引必须排序。索引和TreeSet(底层是AVL)数据结构相同。

在mysql中,索引是一个B树。

复合索引:两个及以上字段联合起来添加一个索引。

# 16.1 语法

创建索引

create  index  emp_ename_index  on  emp(ename) ;

​		给emp表的ename字段添加索引,命名:emp_ename_index

删除索引

drop  index  emp_ename_index  on  emp;

​		将emp表上的emp_ename_index索引对象删除

检查是否有索引

explain  *  from   emp   where   ename  =‘XXX’;

# 16.2 索引失效

1.尽量避免模糊查询时以“%”开始。

2.使用 or 关键字时两边的字段都要有索引,否则不会调用索引。

3.使用复合索引的时候,没有使用左侧的列查找,索引会失效

4.在where中索引列若参与的运算,索引会失效。

5.在where中索引列使用了函数,索引会失效。

......

# 16.3索引分类

索引是各种数据库进行优化的重要手段,优化的时候优先考虑的就是索引。

分类一:单一索引、复合索引。

分类二:主键索引、唯一性索引(在有unique约束的字段上添加索引)

# 17、视图(view)

创建视图对象:create view dept2_view as select * from dept2;

注:上面as关键字后的语句必须是DQL语句。

删除视图:drop view dept2_view;

对视图对象的增删改查,会导致原表被操作。

视图本质就是将一块SQL语句进行封装,以便复用时节省空间。

如:

create  view	emp_dept_view

asselect

​			e.ename ,  e.sal , d.dname

​		from

​			emp e

​		join

​			dept d

​		on

​			e.deptno = d.deptno ;

as 后面的整块SQL语句被封装进了emp_dept_view中

# 18、数据库设计范式

目的:设计合理的数据库表,避免数据冗余、空间浪费。

分类:

​ 第一范式:要求任何一张表必须有主键,每一个字段的原子性不可再分。

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

​ 第三范式:建立在第二范式之上,要求所有非主关键字直接依赖主键,不要产生传递依赖。

# 18.1 第一范式

最核心最重要的范式,所有表的设计都要满足。

有主键,且字段内容不可再分的表满足第一范式。

# 18.2 第二范式

学生编号(复合主键) 教师编号(复合主键) 学生姓名 教师姓名
1001 001 张三 王老师
1002 002 李四 赵老师
1003 001 王五 王老师
1001 002 张三 赵老师

这种表不符合第二范式,因为学生只依赖学生编号,老师只依赖教师编号,数据易冗余。

为了满足第二范式,要将上面的表分解成多个子表(如下)。

学生表

学生编号(pk) 学生名字
1001 张三
1002 李四
1003 王五

教师表

教师编号(pk) 教师姓名
001 王老师
002 赵老师

学生教师关系表

id(pk) 学生编号(fk) 教师编号(fk)
1 1001 001
2 1002 002
3 1003 001
4 1001 002

多对多设计技巧:多对多,三张表,关系表两个外键。

# 18.3 第三范式

学生编号(pk) 学生姓名 班级编号 班级名称
1001 张三 01 一班
1002 李四 02 二班
1003 王五 03 三班
1004 赵六 04 四班

上标满足第一、二范式。

不满足第三范式,因为班级名称依赖班级编号,而班级编号又依赖学生编号,这就产生了传递依赖,会有数据冗余。

为满足第三范式,可以将上标拆成两张表(如下)。

班级表

班级编号(pk) 班级名称
01 一班
02 二班
03 三班
04 四班

学生表

学生编号(pk) 学生姓名 班级编号(fk)
1001 张三 01
1002 李四 02
1003 王五 03
1004 赵六 04

第三范式设计技巧:一对多,两张表,多的表,加外键。

# 18.4 总结表的设计

一对多:

​ 一对多,两张表,多的表加外键。

多对多:

​ 多对多,三张表,关系表两个外键。

一对一:

​ 若字段过多,则要考虑拆成多个更小的表,并用外键加以联系。

​ 一对一,外键唯一。

不过实践和理论之间存在偏差。

从实践上来说,设计表的最终目的都是为了满足客户的要求,有时会拿冗余换执行速度。因为在sql中,表和表之间连接次数越多,效率越低。(笛卡尔积)

# 可参考资料:

数据库范式:https://www.zhihu.com/question/24696366/answer/29189700 (opens new window)

The post above ended Thanks for your reading
Come on! Write some comments, and your suggestions will improve the quality of my creative!
FRIEND ME
QQ
WeChat
Post Author: Mitchell
Post Link: /
Copyright Notice: All articles/posts in this website are licensed under BY-NC-SA unless stating additionally.
Enable Read Mode
COMMENTS
PLAYLIST
TABLE OF CONTENTS
DEFAULT