MySQL数据库

DQL语句

MySQL的简介

卸载

1、第一步:双击安装包进行卸载删除

2、第二步:删除目录:

​ 把C:\programData下面的MySQL目录干掉

​ 把C:\program Files(x86)下面的MySQL目录干掉

查看MyS0QL的服务

1、计算机=>邮件=>管理=>服务和引用程序 => 服务 =>找MySQL服务

MySQL的服务,默认是启动的状态,只有启动了mysql才能使用

默认情况下是自动“启动”,自动启动表示下一次重启操作系统的时候自动启动该服务

可以在服务上点击右键

​ 启动

​ 重启服务

​ 停止服务

还可以改变服务的默认配置

​ 服务上点击右键,属性,然后可以选择启动方式:

​ 自动

​ 手动

​ 禁用

在windows系统中怎么 用命令启动mysql
net stop 服务名称;			#关闭服务
net start 服务名称;			#开启服务
登录mysql
mysql -uroot -p
查看mysql 中有哪些数据库
show databases;
怎么选择使用某个数据库
use 数据库名称;
创建数据库
create database 数据库名称;
导入数据库
source 文件全路径名称
执行脚本中的所有sql语句
注意:全路径中不要有中文
数据库中最基本的单位是表:table
  • 数据库中是一表格的形式表示数据的
  • 因为表比较直观
  • 任何一张表都有行和列:
  • 行:被称为数据/记录
  • 列:被称为字段
  • 了解一下:
  • 每一个字段都有:字段名、数据类型、约束等属性。
  • 字段名可以理解,是一个普通的名字,将名字就行
  • 数据了类型:字符串,数字,日期等。
  • 约束:约束也有很多,其中一个叫做唯一性约束,这种约束添加之后,该字段中的数据不能重复
关于SQL语句的分类

SQL语句有很多,最后进行分门别类,这样更容易记忆

分为

  • DQL:
    • 数据库查询语言(凡是带有select关键词的都是查询语句)
    • select …
  • DML:
    • 数据库操作语言(凡是对表中的数据进行增删改的都是DML)
    • insert dalete update
    • insert 增
    • delete 删
    • updata 改
    • 这个主要是操作表中的数据data
  • DDL:
  • 数据定义语言
  • 凡是带有create、drop、alter的都是DDL
  • DDL主要操作的是表的结构。不是表中的数据
  • create:新建,等同于增
  • drop:删除
  • alter:删除
  • 这个增删改和DML不同,这个主要是对表结构进行操作
  • TCL:
    • 是事务控制语言
    • 包括:
    • 事务提交:commit;
    • 事务回滚:rollback
  • DCL:
    • 是数据控制语言
    • 例如:授权grant、撤销权限revoke…

简单查询语句

怎么查看表中的年数据
select * from 表名;	 // 统一执行这个sql语句。
怎么查看表中数据结构
desc 表名;
查看数据库的版本号:
select version();
查看当前使用的是哪个数据库
select detabase();
查看数据库中有哪些表格
show tables;

简单查询

查询字段
select 字段名 from 表名;

其中要注意

select和from都是关键字。字段名和表名都是标识符

强调

对于SQL语句来说,是通用的,所有的SQL语句以“;”结尾。sql语句不区分大小写

查询多个字段:

使用逗号把要查询的字段隔开“,”

select 字段名,字段名,from 表名

查询多个字段

第一种方式:可以把每个字段名都写上
第二种方式:可以使用*号来代替所有字段,这种方式的缺点是效率低,可读性差,在			实际开发中不建议,可以自己玩没问题
给字段起别名

使用as关键字起别名

select 字段名1,字段名2 as 别名 from 表名;
// 解释给字段2起别名进行查询

注意

只是将显示的查询结果列名显示为别名,原来列名并没有修改,select语句永远都不会进行修改操作的(因为只负责查询)
as关键字可以直接省略不写,使用空格代替“ ”
别名中是不能使用空格的,加了会报错,如果一定要使用空格,使用单引号,或单引号括起来,建议使用单引号。因为有个别其他数据库双引号使用不了

实例:计算员工年薪? sal * 12

select empno,sal*12 as 年薪 from emp;

注意

字段可以使用数学表达式
别名是中文报错的话,可以用单引号括起来

条件查询

什么是条件查询

不是将表中所有数据都查询出来。是查询出来符合条件的

语法格式

select 
	字段
from
	表名
where
	条件;
都有哪些条件?
= 等于
格式:
select 字段1,字段2 from 表名 where 字段1 = 800;
// 这是查询字段1等于800的显示出来
<>!= 不等于
格式:
// 查询薪资不等于800的员工姓名和编号?
select 员工编号,员工姓名 from 表名 where 薪资 != 800;
select 员工编号,员工姓名 from 表名 where 薪资 <> 800;	// 小于号和大于号组成的不等于号
< 小于
格式:
select 薪资,姓名 from 表名 where 薪资 < 800
> 大于
格式:
select 薪资,姓名 from 表名 where 薪资 > 800
= 大于等于
格式:
select 薪资,姓名 from 表名 where 薪资 = 800

between … and … 两个值之间,等同于 >= and <=

#查询薪资在声明条件范围内
# 格式:
# 方式一:>= and <=
select 薪资,姓名 from 表名 where 薪资 >= 700 and 薪资  <= 800;

# 方式二:between...and...
select 
	薪资,姓名 
from
	表名
where 
	薪资 between 700 and 800;

注意:条件不许是左小右大,between and 是闭区间,包括两端的值。

is null 为null (is not null 不为空)

# 查询哪些员工的津贴/补助为null?
select 员工编号,员工姓名,工资,津贴 from 表名 where 津贴 is null;

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

#查询员工补助不为null
select 员工编号,员工姓名,工资,津贴 from 表名 where 津贴 is not null;

and 并且

# 查询工作岗位是MANAGER并且工资大于2500	的员工信息是?
select
	员工编号,员工姓名,工作岗位,工资
from
	表名
where 
	job = 'MANAGER' and sal > 2500;

or 或者

# 查询工作岗位是MANAGER和SALESMAN的员工是?
select 
	员工编号,员工姓名,工作岗位,工资
from
	表名 
where 
	job = ‘MANAGER’ or job = ‘SALESMAN’

注意:andor的优先级,and语句先执行,如果or需要先执行,需要用括号括起来

in 包含,相当于多个or(not in 不在这个范围中)

# 查询工作岗位是MANAGER和SALESMAN的员工?
select 
	员工编号,员工姓名,工作岗位
from 
	表名 
where 
	工作岗位 in('MANAGER','SALESMAN');

注意:in不是一个区间。in后面跟的是具体的值

#查询薪资是800和5000的员工信息?(上面语句和下面语句一样)
select ename,sal from emp where sal  = 800 or sal = 5000

not not 可以取非,主要用在 is 或 in 中

is null			# 表示字段值为null的信息
is not null 	# 表示字段值不不为null的信息
in 				# 显示包含在括号中的所有属性
not in 			# 表示显示不包含括号中的所有属性

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

称为模糊查询,支持%或下划线匹配
%:任意多个字符
下划线:任意一个字符

案例1:找出名字中含有o的?
select 字段1 from 表名 where 字段1 like '%o%';

案例2:找出以T结尾的?
select 字段1 from 表名 where 字段 like '%T';

案例3:找出第三字母是R的
select 字段1 from 表名 where 字段 like '__R';

注意:如果需要查找包含下滑线的,下划线前面一定要加'\'进行转义

排序

案例

#查询所有员工薪资,排序?

默认升序
select 
	字段1,字段2
from 
	表名
order by
	字段2;	
	
指定升序
select 
	字段1,字段2
from
	表名
order by
	字段2 asc;
指定降序
select 
	字段1,字段2
from
	表名
order by
	字段2 desc;		// 这个可以不写,默认就是升序
多个字段排序
# 查询员工名字和薪资,要求按照薪资升序,如果薪资一样的话,在按照名字升序排列。
select 
	名字,薪资
from
	表名
order by
	薪资 asc,名字 asc;		// 薪资在前起主导,只有薪资相等的时候,才会考虑启用名字排序	
了解:根据字段的位置也可以排序
select 名字,工资 from 表名 order by 2;	// 2表示第二列。第二列是工资
按照查询结果的第2列工资排序。
了解一下,不建议在开发中这样写,因为不健壮。因为列的顺序很容易发生改变,列顺序修改之后,2就废了。
综合一点的案例:
# 找出工资在1250到3000之间的员工信息,要求按照薪资顺序排列
select
	enamel,sal
from 
	emp
where
	sal between 1250 and 3000
order by
	sal desc;
	
-----------------------------------------------------------------
# 关键顺序不能变:
select
	...
from 
	...
where 
	...
order by
	...
_________________________________________________________________
# 以上语句的执行顺序必须掌握:
	第一步:from
	第二步:where
	第三步:select
	第四步:order by(排序总是最后执行!

数据处理函数/单行处理函数

lower转换小写
upper转换大写
substr取子串(sybstr(被截取的字符串,起始下标,截取的长度))
length取长度
trim去空格
str_to_date将字符串转换成日期
data_format格式化日期
format设置千分位
round四舍五入
rand()生成随机数
ifnull可以将null转换成一个具体值
数据处理函数又被称为单行处理函数

单行处理函数的特点:一个输入对应一个输出。

和单行处理函数相对的是:多行处理函数。(多行处理函数的特点:多个输入,对应一个输出!)

单行处理函数常见的有哪些
lower 转换小写
# 把字段的所有值都转换成小写
select lower(字段1) from 表名;
select lower(字段1) as 姓名 from 表名;		// 起别名
upper 转换大写
# 把字段的所有值都转换成大写
select upper(字段1) from 表名;
select upper(字段1) as 姓名 from 表名;		// 起别名
substr 取子串(sybstr(被截取的字符串,起始下标,截取的长度))
select substr(字段1,1,1) as 字段1 from 表名; 
注意:起始下标从1开始,没有0

# 找出员工名字第一个字母是A的员工信息?
	第一种方式:模糊查询 
		select 字段1 from 表名 where 字段1 like 'A%';
	第二种方式:substr函数
		select 字段1 from 表名 where sbustr(字段1,1,1) = 'A';
concat 函数进行字符串的拼接
# 把员工编号和员工姓名进行一个拼接
select concat(empno,ename) from emp;

# 案例:首字母大写
select 
	concat(upper(substr(name,1,1)),substr(name,2,length(name)-1)) 
as 
	resull 
from 
	t_student;
length 取长度
# 分别求出每个值的长度并显示出来
select length(ename) as enamelength from 表名;
trim 去空格
# 这句话的意思是在emp表格中查询去掉左右空格的KING的值并显示它的所有的字段信息
# trim()函数时去左右空格的意思
select * from emp where ename = trim(' KING');
round 四舍五入
select 2222 as num from dept;
#结论:select 后面可以跟某个表的字段名(可以等同看做变量名),也可以跟字面量/字面值(数据)。

select round(1236.573,0) as result from emp;
# 表示把round函数中的数据四舍五入,0代表精确到整数,如果是1的话就是保留一位小数,如果是-1的话就保留到十位,以此类推
rand 生成随机数
# 生成一个100以内的随机数保留到整数位,表格有多少数据就生成多少个随机数
select round(rand()*100,0) from emp;

#生成一个0到1的随机数
select rand();
ifnull 可以将null 转换成一个具体值
ifnull是空处理函数。专门处理空的。
在所有数据库当中,只要有NULL参与的数学运算,最终结果就是NULL

注意:NULL只要参与运算,最终结果一定是NULL。为了避免这个现象,需要使用ifnull函数。

ifnull函数用法:ifnull(数据,被当做哪个值)
	如果:“数据”为NULL的时候,把这个数据结构当做哪个值。

# 求员工的工资和补助一年下来有多少?把补助使用ifnull圈起来,如果为null结果按0来计算
select ename,(sal + ifnull(comm,0)) * 12 as yearsal from emp;
case…when…then…when…then…else…end
意思是:当什么时候怎么做,当什么时候怎么做,其他情况怎么办,end结束

# 当员工的工作岗位是MANAGER的时候,工资上调10%,当工作岗位是SALESMAN的时候,工资上调50%,其他正常(注意:不修改数据库,只是将查询结果显示为工资上调)

select 
	ename,job,sal as oldsal,(case job when 'MANAGER' then sal*1.1 when 'SALESMAN'then sal*1.5 else sal end) as newsal 
from 
	emp;

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

多行处理函数的特点:输入多行,最终输出一行。

count计数
sum求和
avg平均值
max最大值
min最小值
注意:

​ 分组函数在使用的时候必须先进行分组,然后才能用。

​ 如果你 没有对数据进行分组,整张表默认为一组

案例:
# 找出最高工资
select max(sal) from emp;

# 找出最低工资
select min(sal) from emp;

# 计算工资和
select sum(sal) from emp;

# 计算平均工资
select avg(sal) from emp;

# 计算员工数量
select count(ename) from emp;
分组函数在使用的时候需要注意哪些?

第一点:分组函数自动忽略NULL,你不需要提前对NULL进行处理。NULL不是一个值是什么都没有。

第二点:分组函数中count(*)和count(具体字段)的区别。count(具体字段):表示统计该字段下所有不为NULL的元素总和.。count(*):统计表当中的总行数。(只要有一行数据count则++),因为每一行数据记录不可能都为NULL,一行数据中有一列不为NULL,则这行数据就是有效的。

第三点:分组函数不能直接使用在where子句中使用,如果非要过滤使用,可以使用having进行过滤

第四点:所有的分组函数可以组合起来一起用。比如

select sum(sal),min(sal),max(sal),avg(sal),count(*) from emp;

分组 查询

什么是分组查询?

在实际的引用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作。这个时候我们需要使用分组查询,怎么进行分组查询呢?

# 格式:
select 
	...
from
	...
group by
	...

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

select 
	...
from 
	...
where
	...
group by
	...
order by
	...
以上关键字的顺序不能颠倒,需要记忆。
执行顺序是什么?
	1.from
	2.where
	3.group by
	4.select
	5.order by
	
案例:
# 案例2:找出每个工作岗位的工资和?
# 实现思路:按照工作岗位分组,然后对工资求和。
select 
	job,sum(sal)
from
	emp
group by
	job;
	
/*
以上这个语句的执行顺序?
	先从emp表中查 询数据
	根据job字段进行分组
	然后对每一组的数据进行sum(sal)
*/	

重点结论:
	在一条select语句当中,如果有group by 语句的话,select后面只能跟:参与分组的字段,以及分组函数。其他的一律不能跟。
	
	
# 案例:2:找出每个部门的最高薪资
select 
	job,max(sal)
from
	emp
group by
	job;
	
# 案例3:找出每个部门,不同工作岗位的最高薪资?
select 
	job,deptno,max(sal)
from
	emp
group by
	deptno,job;
	
	
# 案例4:找出每个部门最高薪资,要求显示最高薪资大于3000的
方式一:(效率低一点)

select
	deptno,max(sal) 
from 
	emp
group by
	deptno
having					// 使用group by分组的使用用having进行条件过滤
	max(sal) > 3000;
	
	
方式二:
select
	deptno,max(sal)
from 
	emp
where 
	sal > 3000
group by 
	deptno;
	
优化策略:wherehaving,优先选择wherewhere实在是完成不了了,在选择为having
大总结
select
	...
from
	...
where
	...
group by
	...
having
	...
order by
	...

以上关键字只能按照这个顺序来,不能颠倒。
执行顺序是
	1.from
	2.where
	3.group by
	4.having
	5.select
	6.order by
	
解释:从某站表中查询数据。
先经过where条件筛选有价值的数据。
对这些有价值的数据进行分组。
分组之后可以使用having继续筛选。
select查询出来。
最后排序输出!

# 综合案例:找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除MANAGER之外,要求按照平均薪资降序排。

select						// 查询
	job,avg(sal) as avgsal
from 						// 所属表格
	emp
where 						// 筛选
	job <=> 'MANAGER'

group by 					// 分组
	job
having 						// 筛选
	avg(sal) > 1500
order by					// 排序
	avgsal desc;			// 降序
	

去除重复记录

把查询结果去除重复记录【distinct】

注意:原表数据不会被修改,只是查询结果去重。distinct只能出现所有字段的最前方。

去重需要使用一个关键字:distinct

select distinct job from emp;

连接查询

什么是连接查询?

从一张表中单独查询,称为单表查询。

emp表和dept表联合起来查询数据,从emp中去员工名字,从dept表中取部门名字。这种夸表查询,多张表联合起来查询数据,被称为连接查询。

连接查询的分类

​ 根据语法的年代分类:

​ SQL92:1992年的时候出现的语法

​ SQL99:1999年的时候出现的语法

​ 我们这里重点学习SQL99

根据表连接方式分类:

内连接:

​ 等值连接

​ 非等值连接

​ 自连接

外连接:

​ 左外连接(左连接)

​ 右外连接(右连接)

全连接(不讲)

笛卡尔积现象

当两张表进行连接查询时,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象。(笛卡尔积发现的,这是一个数学现象。)

怎么避免笛卡尔积现象?

连接时加条件,满足这个条件的记录被筛选出来!

// 表起别名。很重要,效率问题
select
	e.ename,d.dname 
from 
	emp e,dept d
where
	e.deptno = d.deptno;			// SQL92语法。

思考:最终查询的结果条数是14条,但是匹配的次数减少了吗?

​ 还是56次,只不过进行了四选一。次数没有减少。

注意:通过笛卡尔积现象得出,表连接次数越多效率越低,尽量避免表的连接次数

内连接

内连接的特点:完成能够匹配上这个条件的数据查询出来。

内连接之等值连接

条件被称为等量关系,所以被称为等值连接

案例:查询每个员工所在部门名称,显示员工名和部门名?

emp e和dept d表进行连接,条件是:e.deptno = d.deptno

SQL92语法:
select
	e.ename,d.dname
from
	emp e,dept d
where
	e.deptno = d.deptno;
// SQL92的缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放到了where后面。

__________________________________________________________________
	
SQL99语法:(join前面也可以加上 inner 也可以不写)
select
	e.name,d.dname
from
	emp e
join
	dept d
on
	e.deptno = d.deptno;
// SQL99的优点:表连接的条件是独立的,连接之后如果还需要进一步筛选,在往后继续添加where
内连接之非等值连接

条件不是一个等量关系,称为非等值连接。

案例:找出员工的薪资等级,要求显示员工名、薪资、薪资等级?

select 
	e.ename,e.sal,s.grade
from 
	emp e
join
	salgrade s
on
	e.sal between s.losal and s.hisal;
内连接之自连接

自己的表和自己的表连接就是自连接,一张表看做两张表连接

案例:查询员工的上级领导,要求显示员工名和对应的领导名

select 
	a.ename as '员工名',b.ename as '领导名'
from
	emp a
join
	emp b
on 
	a.mgr = b.empno;		// 员工的领导编号 = 领导的员工编号
外连接

right join 中间是有一个outer,可以省略,也可以写,写上可读性强

带有right的是右外连接,又叫做右连接。

带有left的是左外连接,又叫做左连接。

任何一个右连接都有左连接的写法。

任何一个左连接都有右连接的写法。

右外连接
select
	e.ename,d.dname
from
	emp e right join dept d		// emp e right outer join dept d
on
	e.deptno = d.deptno;

/*

right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表。在外连接当中,两张表连接,产生了主次关系,如果是内连接时完全平等的

*/ 
左外连接
select 
	e.name,d.dname
from 
	dept d left join emp e		// dept d left outer join emp e
on
	e.deptno = d.deptno;

// 做外连接和右外连接是一样的,只是顺序不一样

结论:外连接的查询结果条数一定是 >= 内连接的查询结果条数?

案例:
案例1:查询每个员工的上级领导,要求显示所有员工的名字和领导名?
select 
	e.ename as '员工名',d.ename as '老板名'
from 
	emp e right outer join emp d
on 
	d.empno = e.mgr;
三张表,实战表怎么连接
语法:
select
	...
from
	a
join
	b
on
	a和b的连接条件
join
	c
on
	a和c的连接条件
right join
	d
on
	a和d的连接条件

/*
一条SQL中内连接和外连接可以混合。都可以出现!
*/
案例:找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级?
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;
	
案例:找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名、领导名、部门名、薪资、薪资等级?
select 
	e.ename as '员工名',e.sal,d.dname,s.grade,l.ename as '领导名'
from
	emp e 
join
	dept d
on
	e.deptno = d.deptno
join
	salgrade s
on
	e.sal between s.losal and s.hisal
left join
	emp l
on
	e.mgr = l.empno;

子查询

什么是子查询

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

子查询可以出现的位置
select
	...(select)
from
	...(select)
where
	...(select)
where子句中的子查询

注意:where子句中是不能直接出现分组函数的

案例:找出比最低工资高的员工姓名和工资?
实现思路:
第一步:查询最低工资是多少
	select min(sal) from emp;

第二步:找出工资大于800select ename,sal from emp where sal > 800;
	
第三步:合并
	select ename,sal form emp where sal > (select min(sal) from emp);

from子句中的子查询

注意:from后面的子查询,可以将子查询的查询结果当做一张临时表。

案例:找出每个岗位的平均工资的薪资等级(按照岗位分组求平均值)

第一步:找出每个岗位的平均工资(按照岗位分组求平均值)
select job,avg(sal) from emp group by job;

第二步:客服心理障碍把以上的查询结果就当做一张真实存在的表t.
select 
	t.*,s.grade
from
	(select job,avg(sal) as avgsal from emp group by job) t
join
	salgrade s
on
	t.avgsal between s.losal and s.hisal;


select后面出现的子查询(了解)
案例:找出每个员工的部门名称,要求显示员工名,部门名?
select
	e.ename,e.deptno,(select d.dname from dept d where 	e.deptno = d.deptno) as dname
from
	emp e;
	
注意:在select后面的子查询只能返回一个结果,多一个结果都会报错

union合并查询结果集

案例:查询工作岗位是MANAGER和SALESMAN的员工?

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

以上语句使用union可以实现同样的结果,如下

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

/*

union的效率要高一些。对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的翻,但是union可以减少匹配的次数。在减少匹配次数的情况下,还可以完成两个结果集的拼接。
	
*/

比较:
a连接b连接c
a 10条记录
b 10条记录
c 10条记录
匹配次数是:1000

a连接b一个结果:10*10 --> 100次
a连接c一个结果:10*10 --100次
使用union的话是:100+100= 200次。(union把乘法变成了加法运算)
union在使用的时候有注意事项?

union在结果进行结果集合并的时候,要求两个结果集的列数相同并且列和列的数据类型也相同

limit

limit作用

是将查询结果集的一部分取出来,通常使用在分页查询当中。

分页的左右是为了提高用户的体验,因为一次全部都查出来,用户体验差。可以一页一页翻页看。

limit用法

完整用法:limit startIndex,leng

​ srartIndex是其实下标,leng是长度。

​ 起始下标从0开始。

缺省用法:limit 5; 这是去前5

案例:按照薪资江西,取出排名在前五的员工?
select 
	ename,sal
from 
	emp
order by
	sal desc
limit 5;		// 取前5条数据,也可以这样写 limit 0,5;

注意:mysql蛋黄粽limit在order by之后执行!!!

案例:取出工资排名在[3-5]名的员工?
select 
	ename,sal
from
	emp
order by
	sal desc
limit
	2,3; 	// 2表示起始位置从下标2开始,就是第三条记录。3表示长度

案例:取出工资排名在[5-9]名的员工?

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

每页显示3条记录

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

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

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

​ 第4页:limit 6,3 [9 10 11]

每页显示pageSize条记录

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

// 百度的搜索显示页数使用java代码的表达
   
public static void main(String[] args){
   // 用户提交过来一个页码,以及每	页显示的记录条数
   int pageNo = 5;		// 第五页
   int pageSize = 10;	// 每页显示的记录条数
   
   int startIndex = (pageNo - 1) * pageSize;	//每页显示10条
   String sql = "select ... limit" + startIndex +"pageSize";
}
limit记忆公式:
limit (pageNo - 1)*pageSize , pageSize

DQL语句的大总结

select				// 选择需要查询的
	...
from				// 所属表
	...
where				// 分组前过滤条件
	...
group by			// 分组
	...
having				// 分组后滤条件
	...
order by			// 排序
	...
limit				// 分页
	...
	
/*

执行顺序:
	1.from
	2.where
	3.group by
	4.having
	5.select
	6.order by
	7.limit..

*/

DDL语句

表的创建

建表的语法格式:(建表属于DDL语句,DDL包括 create drop alter)
create table 表名(
   字段名1 数据类型,
   字段名2 数据类型,
   字段名3 数据类型
);

/*

表名:建议以t_ 或者 tbl_ 开始,可读性强。见名知所意
字段名:将名知意 表名和字段名都数据标识符。

*/
关于mysql中的数据类型?

很多数据类型,我们只需要长掌握 一些常见的数据类型即可

varchar可变长度的字符串,比较智能,节省空间,会根据实际的数据长度动态分配空间。(最长255位)优点:节省空间,需要动态的分配空间,速度慢
char定长字符串,不管实际的数据长度是多少。分配固定长度的空间去存储数据。(最长11位)优点:不需要动态分配空间,速度快。缺点:使用不恰当的时候可能会导致空间的浪费。
int数字中的整数型。等同于java中的int
bigint数字中的长整形。等同于java中的long
dauble双精度浮点型数据
date短日期
datetime长日期
clob字符大对象,最多可以存储4G的字符串。比如:传出一篇文章,存储一个说明 。超过255个字符的都要采用字符大对象来存储
blob二进制大对象,专门用来存储图片、声音、视频等流媒体数据。往BLOB类型的字段上插入数据的时候,例如插入一个图片、视频等。你需要使用IO流才行
float单精度浮点型数据
案例:创建一个学生表?

学号、姓名、年龄、性别、邮箱地址

create table t_student(
	no int,						#学号
   	name varchar(32),			#姓名
   	sex char(1),				#年龄
   	age int(3),					#性别
   	email varchar(255)			#邮箱地址
);
删除表
drop table t_sutdent;			// 这样删除当这张表不存在的时候会报错!

drop table if exists t_student; // 如果这张表存在的话,删除

插入数据insert(DML)

语法格式:
insert into 表名(字段名1,字段名2,字段名3....values(1,2,3);
/*
注意:字段名和值要一一对应。什么是一一对应?
	数量要对应。数据类型要对应。
*/
在创建的表中添加信息
insert into t_student(no,name,sex,age,email) values(1,'zhangsan','m',20,'zhansan@123.com');

insert into t_student(email,name,sex,age,no) values('lisi@123.com','lisi','m',23,2);

/*

注意:insert语句但凡是执行成功了,那么必然会多一条记录。
没有给其他字段指定值的话,默认值为NULL.

*/
创建的时候指定默认值(default)
drop table if exists t_student;
create table t_student(
	no int,
   name varchar(32),
   sex char(1) default "m",
   age int(3),
   email varchar(255)
); 
insert语句中的“字段名”可以省略吗

可以

但是需要注意的是 :前面的字段名省略的话,等于都写上了!所以值也要都写上!

insert into t_student values(2,'lisi','f',20,'lisi@123.com')
insert插入日期
数字格式化:format
select ename,sal from emp;
格式化数字:format(数字,‘格式’)
select ename,format(sal,'$999,99') as sal from emp;
str_to_date:将字符串varchar类型转换成data类型
mysql的日期格式:
%Y 年
%M 月
%D 日
%h 时
%i 分
%s 秒

insert into t_user(id,name,birth) values(1,'zhangsan',str_to_date('01-10-1990','%D-%M-%Y'));

/*
如果你提供的日期字符串是这个格式,str_to_data函数就不需要%Y—%M—%D了
*/

insert into t_user(id,name,birth) values(1,'zhangsan',str_to_date('1990-10-01'));
date_format:将date类型转换成具有一定格式的varchar字符串类型。

date_format函数怎么用?

​ date_format(日期类型数据,‘日期格式’)

​ 这个函数通常使用在查询日期方面。设置展示的日期格式。

select id,name,date_format(birth,'%m/%d/%Y') as birth from t_user;

注意:数据库中的有一条命名规范:

​ 所有的标识符都是全部小写,单词和单词之间使用下划线进行衔接。

date和datetime两个类型的区别?

date是短日期:只包括年月日信息。

datetime是长日期:包括年月日时分秒信息。

drop table if exists t_user;
create table t_user(
	id int,
   name varchar(32),
   birth date,
   create_time datetime
);


id是整数
name是字符串
birth是短日期
create_time是这条记录的创建时间:长日期类型

mysql短日期默认格式:%Y-%m-%d
mysql长日期默认格式:%Y-%m-%d %h:%i:%s

// 插入短时间和长时间的案例
insert into t_user(id,name,birth,create_time) values(1,'zhangsan','1990-10-01','2022-9-10 16:37:32')
now() 函数

now函数,获取系统当前时间并且获取的时间带有:时分秒信息!!!是datetime类型的。

insert into t_user(id,name,birth,create_time) values(1,'lisi','1992-10-23',now())
insert如何插入多条数据
insert into t_user(id,name,birth,create_time) values
(1,'zhangsan','1992-10-23',now()),
(2,'lisi','1992-10-23',now()),
(3,'wanwu','1892-10-23',now()),
(4,'lisi','1972-11-23',now());

DML语句

修改update

语法格式
update 表名 set 字段名1=1,字段名2=2,字段名3=3... where  条件;

注意:没有条件限制会导致所有数据全部更新。如果没有where条件限制,会直接更改所有的

update t_user set id = 2,birth = '2000-10-11',create_time = now() where name = 'lisi';

删除数据 delete

语法格式
delete from 表名 where 条件;

注意:没有条件,整张表的数据会全部删除!

delete from t_user where id = 2;

删除所有

delete from t_user;	

快速创建表(表的复制)

create table emp2 as select * from emp;
/*
原理:
	将一个查询结果当做一张表新建
	这个可以完成表的快速复制
	表创建出来,同时表的数据也存在了
*/··
把一个查询结果查询出来新建
create table mytable as select empno,ename from emp where job = 'MANAGER';

将查询结果插入到一张表当中

insert into dept_bak select * from dept;

快速删除表中的数据

delete删除(这中属于DML语句)
delete from dept_bak where deptno = 10;   //这中删数据的方式比较慢

/*
delete语句删除数据的原理?
	表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会释放
	这中删除的缺点是:删除的效率比较低
	这种删除有点是:支持回滚,后悔了可以在恢复数据

*/
truncate删除(这种属于DDL操作。)
truncate table dept_bak;/*
truncate语句删除数据的原理?
	这种删除效率比较高,表被一次截断,物理删除
	这种删除缺点,不支持回滚
	这种删除优点:快速
*/

大表非常大,上亿条记录

​ 删除的时候,使用delete,也许需要执行1个小时才能删除完,效率较低

​ 可以选择使用truncate删除表中的数据。只需要不到1秒钟的时间就删除结束。效率比较高。但是使用truncate之前,必须仔细询问客户是否真的要删除,并警告删除之后不可恢复

对表结构的增删改(DDL语句)

什么是对表结构的修改?

​ 添加一个字段,删除一个字段,修改一个字段

对表结构的修改需要使用:alter

DDL包括:create drop alter

第一:在实际的开发中,需求一旦确定之后,表一旦设计好之后,很少的进行表结构的修改。因为开发进行中的时候,修改表结构,成本比较高的。
第二:由于修改表结构的操作很少,所以我们不需要掌握,如果有一天真的要修改表结构,你可以使用工具
修改表结构的操作是不需要写到java程序中的,实际上也不是java程序的范畴。

约束

什么是约束

约束的对应的英语单词:constraint

在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性、有效性!

约束的作用就是为了保证:表中的数据有效!

约束包括哪些

非空约束:not null

唯一性约束:unique

主键约束:primary key (简称PK)

外键约束:foreign key (简称FK)

检查约束:check (mysql不支持,oracle支持)

我们这里重点学习四个约束:
not null
unique
primary key
foreign key
非空约束:not null

非空约束not null 约束的字段不能为null

drop table if exists t_vip;
create table t_vip(
	id int,
   name varchar(255) not null	// not null只有列级约束,没有表级约束
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');

唯一性约束:unique
drop table if exists t_vip;
create table t_vip(
	id int,
   name varchar(255) unique,		# 设置姓名的唯一性
   email varchar(255)
);

# 往表格中插入新的数据
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');
insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');
select * from t_vip;
新需求:name和email两个字段联合起来具有唯一性
drop table if exists t_vip;
create table t_vip(
	id int,
   name varchar(255) unique,	// 约束添加在列后面的,这种约束被称为列级约束
   email varchar(255) unique
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'zhangsan','san@555.com');

/*
这张表这样创建时不符合我以上“新需求”的
这样创建表示:name具有唯一性,email具有唯一性。各自唯一。

一下这样的数据是符合我们的新需求的。
但如果采用以上的方式创建表的话,肯定是创建失败,因为’zhangsan‘和’zhangsan‘重复了。
怎么创建这样的表,才能符合新需求呢?
*/

drop table if exists t_vip;
create table t_vip(
	id int,
   name varchar(255),
   email varchar(255),
   unique(name,email)	// 约束没有添加在列后面,这种约束被称为表级约束
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'zhangsan','san@555.com');
select * from t_vip;
什么时候使用表级约束呢?

需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。

unique 和not null可以联合吗?
drop table if exists t_vip;
create table t_vip(
	id int,
   name varchar(255) not null unique
);
/*
在mysql当中,如果一个字段同时被not null 和unique约束的话,该字段自动编程主键字段。
*/
主键约束 primary key (简称PK)
主键约束的相关术语?

​ 主键约束:就是一种约束。

​ 主键字段:该字段上添加了主键约束,这样的字段叫做主键字段

​ 主键值:主键字段中的每一个值叫做:主键值。

什么是主键?有啥用?

​ 主键值是每一行记录的唯一标识。

​ 主键值是每一行记录的什么真好。

记住:

​ 任何一张表都应该有主键,没有主键,表无效!

主键的特征

​ not null + unique (主键值不能为NULL,同时也不能重复!)

怎么添加主键约束
drop table if exists t_vip;
create table t_vip(
	id int primary key,		// 一个字段做主键,叫做:单一主键
   name varchar(255)
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi')

x drop table if exists t_vip;
create table t_vip(   
   id int,    
   name varchar(255),
   primary key(id,name)	// 两个字段联合起来做主键叫做复合主键
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi')

在实际开发中不建议使用:复合主键。建议使用单一主键!

因为主键值存在的意义就是这行记录的身份证号,只要意义达到即可,单一主键可以做到符合主键比较复杂,不建议使用

结论:一张表,主键约束只能添加一个不能添加俩

主键值建议使用

​ int,bigint,char,等类型.

​ 不建议使用:varchar来做主键。主键值一般都是数字,一般都是定长的

主键除了:单一主键和复合主键之外,还可以这样进行分类?

​ 自然主键:主键值是一个自然数,和业务没有关系。

​ 业务主键:主键值和业务紧密关联,例如拿银行卡账号做到不重复就行,不需要有意义。

​ 业务主键不好,因为主键一旦和业务挂钩,那么当业务发生变动的时候。可能会影响到主键值,所以业务主键不建议使用,尽量使用自然主键.

在mysql当中,有一种机制,可以帮助我们自动维护一个主键值?
drop table if exists t_vip;
create table t_vip(
	id int primary key auto_increment, #auto_increment表示自增,从1开始以1递增
   name varchar(255)
);
insert into t_vip(name) values("zhangsan");
insert into t_vip(name) values("zhangsan");
insert into t_vip(name) values("zhangsan");
insert into t_vip(name) values("zhangsan");
insert into t_vip(name) values("zhangsan");

外键约束(foreign key,简称FK)
外键约束涉及到的相关术语:

​ 外键约束:一种约束(foreign key)

​ 外键字段:该字段上添加了外键约束

​ 外键值:外键字段当中的每一个值

业务背景:

请设计数据库表,来描述班级和学生的信息?

第一种方案:班级和学生储存在一张表中

分析以上方案的缺点:

​ 数据冗余,空间浪费

​ 这个设计是比较失败的

第二周方案:班级一张表、学生一张表??

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-quQOE0Un-1666069104434)(C:%5CUsers%5Ckang%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20220911162333746.png)]

当cno字段没有任何约束的时候,可能会导致数据无效。可能出现一个102,但是102班级不存在所以为了保证cno字段就是外键字段。cno字段中的每一个值都是外键值

注意:

​ t_class是父亲

​ t_student是子表

​ 删除表的顺序?

​ 先删子,在删父。

​ 创建表的顺序?

​ 先创建父,在创建子

​ 删除数据的顺序?

​ 先删子,在删父

​ 插入数据的顺序?

​ 先插入父,在插入子。

drop table if exists t_student;
drop table if exists t_class;
create table t_class(
	classno int primary key,
    classname varchar(225)
);
create table t_student(
	no int primary key auto_increment,
    name varchar(255),
    cno int,
    foreign key(cno) references t_class(classno)
);
insert into t_class(classno,classname) values(100,'第二中学高三1班');
insert into t_class(classno,classname) values(101,'第二中学高三2班');

insert into t_student(name,cno) values('zhansan',100);
insert into t_student(name,cno) values('lishi',101);
insert into t_student(name,cno) values('wanwu',100);
select * from t_student;
select * from t_class;
思考:子表中的外键引用的父表中的某个字段,被引用的这个字段必须是主键吗?

​ 不一定是主键,当至少具有unique约束

测试:外键可以为NULL吗?

​ 外键可以为NULL.

存储引擎(了解内容)

什么是存储引擎,有什么用呢?

存储引擎是mysql中特有的一个术语,其他数据库中没有。(oracle有,但是不叫这个名字)

存储引擎这个名字高端大气上档次

实际上存储引擎是一个表存储/组织数据的方式。

不同的存储引擎,表存储数据的方式不同。

怎么给表添加/指定’存储引擎‘呢?
查看存储引擎
show create table t_student;
可以在建表的时候给表指定存储引擎
create table t_student(
	no int primary key auto_increment,
   name varchar(255),
   cno int,
   foreign key(cno) references t_class(classno)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

在建表的时候可以在最后小括号的右边使用:
	ENGINE来知指定存储引擎。
	GHARSET来指定这张表的字符集编码方式
结论:
	mysql默认的存储引擎是:InnoDB
	mysql默认的字符编码方式是:utf8
怎么查看mysql支持哪些存储引擎呢?
命令:show engines \G

mysql支持九大存储引擎,当前5.5.36支持8个。版本不同支持情况不同。

关于存储引擎介绍一下
MyISAAM存储引擎
它管理的表具有一下特征:
  • 使用三个文件表示每个表:
  • 格式文件 - 存储表结构的定义(mytable.frm)
  • 数据文件 - 存储表行的内容(mytable.MYD)
  • 索引文件-存储表上索引(mytable.MYD):索引是一本数的目录,缩小扫描范围,提示可被转换为压缩、只读表来节省空间

提示一下:对于一张表来说,只要是主键,或者加有unique约束的字段上会自动创建索引。

MyISAM存储引擎特点

  • 可被转换为压缩、只读表来节省空间

  • 这是这中存储引擎的优势

MyISANM不支持事务,安全性低

InnoDB存储引擎

这是mysql 默认的存储引擎,同时也是一个重量级的存储引擎。

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

InnoDB存储引擎最主要的特点是:非常安全

它管理的表具有下列主要特征:
  • 每个InnoDB表在数据库目录中以.frm格式文件表示
  • InnotDB表空间tablespace被用于存储表的内容(表空间是一个逻辑名称。表空间存储数据+索引。)
  • 用COMMIT(提交)、SAVEPOINT及ROLLBACK(回滚)支持事务处理
  • 提供全ACID兼容
  • 在Mysql服务器崩溃后提供自动恢复
  • 多版本(MVCC)和行级锁定
  • 支持外键及引用的完整性,包括级联删除和更新

InnoDB最大的特点就是支持事务:

​ 以保证数据的安全。效率不是很高丙炔也不能压缩,不能转换为只读,不能很好的节省存储空间。

MEMORY存储引擎

使用MKMORY存储引擎的表,其数据存储在内存中,且行的长度固定,这两个特点使的MEMORY存储引擎非常快。

MEMORY 存储引擎管理的表具有下列特征:
  • 在数据库目录内,每个表均以.frm格式的文件表示。
  • 表数据及索引被存储在内存中。(目的就是块,查询快)
  • 表级锁机制。
  • 不能包含 TEXT或BLOB字段

MEMOEY 存储引擎以前被称为HEAP引擎。

MEMORY引擎的优点:查询效率是最高的。

MEMORY引擎的缺点:不安全,关机之后数据消失。因为数据和索引都是在内存当中。

事务

什么还是事务

一个事务就是一个完整的业务逻辑。

是一个最小的工作单元,不可在分。

什么事是一个完整的业务逻辑?

​ 假设转账,从A账户向B账户转账10000。

​ 将A账户的钱减去10000(update语句)

​ 将B账户的前加上10000(update语句)

​ 这就是一个完整的业务逻辑。

​ 以上的操作是一个最小的工作单元,要么同时成功,要么同时失败,不可再分。这两个updete语句要求必须同时成功或者同时失败,这样才能保证钱是正确的。

只有DML语句才会有事务这一说,其他语句和事务无关
insert

delete

update

只有以上的三个语句和事务有关系,其他都没有关系。

因为只有以上的三个语句是数据库表中进行增,删,改的。

只要你的操作一旦设计到数据的增、删、改,那么就一定要考虑安全问题。

数据安全第一位。

假设所有的业务,只要一条DML语句就能完成,还有必要存在事务机制吗?

正是因为在做某件是的时候,需要多条DML语句共同联合起来才能完成,

所以事务则没有存在的价值了。

到底是生事务呢?

​ 说到底,说到本质上,一个事务其实就是多条DML语句同时成功,或者同时失败!

事务:就是批量的DML语句同时成功,或者同时失败

事务是怎么做到多条DML语句同时成功同时失败的呢?

InnoDB存储引擎:提供一组用来记录事务生活的日志文件

事务开启了:
insert
insert
delete
update
事务结束了!

在事务的执行过程中,每一条DML的操作都会记录到“事务性活动的日志文件当中”。

在事务的执行活成中,我们可以提交事务,也可以回滚事务。

提交事务是什么意思:

​ 清空事务性活动的日志文件,将数据全部持久化到数据库表中。

​ 提交事务标志着,事务的结束,并且是一种全部成功的结束

回滚事务是什么意思:

​ 将以前所有的DML操作全部撤销,并且清空事务性活动的日志文件

​ 回滚事务标志着,事务的结束。并且是一种全部失败的结束。

怎么提交事务,怎么回滚事务?
commit;			// 提交事务语句
rollback;		// 回滚事务语句(回滚永远都是只能回滚到上一次的提交点!)
事务对应的英语单词是:transaction
自动提交

mysql默认情况下是支持自动提交事务的

什么是自动提交

​ 每执行一条DML语句,则提交一次!

​ 这中自动提交实际上是不符合我们 的开发习惯的,因为一个业务通常是需要多条DML语句共同执行才能完成的为了保证数据的安全必须要求同时成功之后在提交,所以不能执行一条就提交一条

关闭自动提交
start transaction;			// 关闭自动提交的命令
事务包括4个特性
  • A:原子性

  • 说明事务是最小的工作单元。不可再分。

  • C:一致性

  • 所有事务要求,在同一个事务当中,所有 操作必须同时成功,或者同时失败,以保证数据的一致性。

  • T:隔离性

  • A事务和B事务之间具有一定的 隔离。教室A和教室B之间有一道墙,这道墙就是隔离性

  • D:持久性

  • 事务最终结束的一个保障。事务提交,就相当于将没有保存到 硬盘上的数据保存到硬盘上

事务的隔离性

A教室和B教室中间有一道墙,这道墙可以很厚,也可以很薄,这就是事务的隔离级别。这道墙越厚,表示隔离级别就越高。

事务和事务之间的隔离级别有哪些呢?4个级别
  • 读未提交:read uncommitted(最低的隔离级别)

​ 什么是读未提交?

​ 事务A可以读取到事务B未提交的数据。

​ 这种隔离级别存在的问题就是:

​ 脏读现象(Dirty Read)

​ 我们称为读到了脏数据。

​ 这种隔离级别都是理论上的,大多数数据库给力级别都是二档起步

  • 读已提交:read committed

​ 什么是读已提交?

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

​ 这种隔离级别解决了什么问题?

​ 解决了脏读的现象。

​ 这种隔离级别存在什么问题?

​ 不可重复读取数据。

​ 什么是不可重复读取数据呢?

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

这中给力界别是比较真实的数据,没一次读到的数据是绝对的真实,oracle数据库默认的隔离级别是: read committed

  • 可重复读:repeatable read(提交之后也读不到,永远读取的都是刚开启事务时的数据)

​ 什么是可重复读取?

​ 事务A开启之后,不管是多久,每一次在事务读取到的数据都是一致的。即 使事务B将数据已经修改,并提交了,事务A读取到的数据还是没有发生改变,这 就是可重复读。

​ 可重复读节约了什么问题?

​ 解决了不可重复读取数据

​ 可重复读存在的问题是什么?

​ 可以会出现幻影读。

​ 每一次读取到的数据都是幻想。不够真实

早上9点开始开启了事务,只要事务不结束,到晚上9点,读到的数据还是 那样!

读到的是假象。不够真实。

mysql中默认的事务隔离级别就是这个

  • 序列化/串行化:serializable(最高的隔离级别)

​ 这是最高隔离级别,效率最低,解决了所有问题。

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

​ synchronized,线程同步(事务同步)

​ 每一次读取到的数据都是最真实的,并且效率是最低的

查看事务的隔离级别
select @@tx_isolation;
更改事务的隔离级别
// 格式:
set global transaction isolation level 隔离级别;

// 设置读未提交隔离级别
set global transaction isolation level read uncommitted
// 设置读已提交隔离级别
set global transaction isolation level read committed
// 设置重复读隔离级别
set global transaction isolation level repeatable read
// 设置序列化/串行化隔离级别
set global transaction isolation level serializable
验证各种隔离级别

验证:read uncommited

事务1:					事务3use mydb;
						use mydb;
start transaction;				
						start transaction;	
						insert into t_user values('zhangsan');
select * from t_user;			

验证:read committed

事务1:					事务2use mydb;
start transaction;
							use mydb;
select * form t_user;		
							start transaction;	
							insert into t_user values('zhangsan');
select * from t_user;
							commit;
select * from t_user;

验证:repeatable read

事务1:					事务2use mydb;
start transaction;
							use mydb;
select * form t_user;		
							start transaction;	
							insert into t_user values('zhangsan');
select * from t_user;
							commit;
select * from t_user;

验证:serializable

// 更改隔离级别
set global transaction isolation level serializable
事务1:					事务2use mydb;
start transaction;
							use mydb;
select * form t_user;		
							start transaction;	
							insert into t_user values('zhangsan');
select * from t_user;
							commit;

索引

什么是索引

索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。

一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。

索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。

  • 对于一本字段来说,查找某个汉子有两种方式:
  • 第一种方式:一页一页挨着找,直到找到为止,这种查找方式属于全字典扫描。效率比较低。
  • 第二种方式:先通过目录(索引)去定位一个大概的位置,然后直接定位到这个位置,做局域性扫描,缩小扫描的范围,快速的查找。这种方式属于通过索引检索,效率较高。

select * from t_user where name = ‘jack’;

以上的这条SQL语句会去name字段上扫描,为什么?

​ 因为查询条件是:name = ‘jack’

如果name字段上没有添加索引(目录),或者说没有给name字段创建索引,Mysql会进行全扫描,会将name字段上的每一个值都比对一遍。效率比较低。

mysql在查询方面主要就是两种方式:

第一种方式:全表扫描

第二种方式:根据索引检索。

注意:

在实际汇总,汉语字典前面的目录是排序顺序的,按照a…z排序,为什么排序呢?因为只要排序了才会有区间查找这么一说(缩小扫描范围其实就是扫描某个区间罢了)

在mysql数据库当中索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同,二叉树,遵循左小右大原则存放。采用中序遍历方式遍历取数据

在mysql当中,主键上,以及unique字段上都会自动添加索引的

什么条件下,我们会考虑给字段添加索引呢?

​ 条件1:数据量大(到底有多大,这个需要测试,因为每一个硬件环境不同)

​ 条件2:该字段经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描

​ 条件3:该字段很少的DML(insert delete update)操作。(因为DML之后,索引需要重新排序。)

建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。

建议通过主键查询,建议通过unique约束的字段进行查询,效率是比较高的

索引怎么创建
# 给emp表的ename字段添加索引,起名:emp_ename_index
create indexx emp ename_index on emp(ename);
删除索引
# 将emp表上的emp_ename_index索引对象删除。
drop index emp_ename index on emp;
怎么查看一个sql语句是否使用了索引进行检索?
explain select * from emp where ename = 'king'
索引有失效的时候

第一种情况

select * from emp where ename like '%T';

ename上即使添加了索引,也不会走索引,为什么呢?
	原因是因为模糊匹配当中以'%'开头了
	这是一中优化的手段/策略

失效的第二种情况:

使用or的时候会失效,如果使用or那么要求or两边的条件字段都要有索引,才会走索引,如果其中一边有一个字段没有索引,那么另一个字段上的索引也会实现。所以这就是为什么不建议使用or的原因。

失效的第三种情况;

使用符合索引的时候,没有使用左侧的列查找,索引失效
什么是符合索引?
	两个字段,或者更多的字段联合起来添加一个索引,叫做符合索引。
create index emp_job_sal_index on emp(iob,sal);

失效的第四种情况:

where当中索引列参加了运算,索引失效。

失效的第五种情况:

where当中索引列使用了函数
explain select * from emp where lower(ename) = 'smith'
索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引

索引在数据看中分了很多类?

​ 单一索引:一个字段上添加索引。

​ 符合索引:两个字段或者更多的字段上添加索引

​ 主键索引:主键上添加索引

​ 唯一性索引:具有unique约束的字段上添加索引。

​ 注意:唯一性比价弱的字段上添加索引用处不大

视图

什么是视图

view:站在不同的角度去看待同一份数据。

怎么创建视图对象
create view emp_view as select * from emp;
怎么删除4视图对象
drop view dept2_view;

注意:只有DQL语句才能以view的形式创建。

用视图做什么?

我们可以面向视图对象进行增删该查,对视图对象的增删改查,会导致原表被操作(视图的特点:通过对视图的操作,会影响到原表数据。)

面向视图查询
select * from dept2_view;
面向视图插入
insert into dept2_view(deptno,dname,loc) values(60,'SALES','BEIJING');
查询原表数据
select * from dept2;
面向视图删除
delete from dept2_view;
面向视图更新
update emp_dept_view set sal = 1000 where dname = 'ACCOUNTING';
视图对象在实际开发到底有什么用?
create view
	emp_dept_view
as							# as后面只能是查询语句
	select
		e.ename,e.sal,d.dname
	from
		emp e
	join
		dept d
	on
		e.deptno = d.deptno;

假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?

在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。并且利于后期维护,因为修改的时候也只需要修改一个文件的位置就行,只需要修改视图对象所映射的SQL语句

DBA常用命令

导出(在doc命令下使用)
mysqldump 需要导出的数据库名称>导出的路径名称 用户	密码
mysqldump bjpowernode>D:\\bjpowernode.sql -uroot -p123456
删除数据库
drop database bjpowernode;
导入数据库(登录数据库后使用)
source 需要导入的文件的路径名称

数据库设计三范式

什么是数据库设计范式

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

第二范式:奖励在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖

第三范式:建立在第二范式的基础之上,要求所有主键字段字节依赖主键,

设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费

第一范式

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

必须有主键,并且每一个字段都是原子性不可再分。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0wFq0hs-1666069104436)(C:%5CUsers%5Ckang%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20220913142514806.png)]

第二范式

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

背口诀:

​ 多对多怎么设计?

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

第三范式

第三范式建立在第二范式的基础之上

要求所有非主键字典必须字节依赖主键,不要产生传递依赖。

总结表的设计

一对多:

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

多对多:

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

一对一:

​ 一对一放到 一张表就行了

嘱咐一句话

数据库设计三范式是理论上的 。

实践和理论有的时候有偏差

最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。

因为在SQL当中,表和表之间连接 次数越多,效率越低(笛卡尔积)

有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的。

合索引?

两个字段,或者更多的字段联合起来添加一个索引,叫做符合索引。
create index emp_job_sal_index on emp(iob,sal);


失效的第四种情况:

```sql
在where当中索引列参加了运算,索引失效。

失效的第五种情况:

where当中索引列使用了函数
explain select * from emp where lower(ename) = 'smith'
索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引

索引在数据看中分了很多类?

​ 单一索引:一个字段上添加索引。

​ 符合索引:两个字段或者更多的字段上添加索引

​ 主键索引:主键上添加索引

​ 唯一性索引:具有unique约束的字段上添加索引。

​ 注意:唯一性比价弱的字段上添加索引用处不大

视图

什么是视图

view:站在不同的角度去看待同一份数据。

怎么创建视图对象
create view emp_view as select * from emp;
怎么删除4视图对象
drop view dept2_view;

注意:只有DQL语句才能以view的形式创建。

用视图做什么?

我们可以面向视图对象进行增删该查,对视图对象的增删改查,会导致原表被操作(视图的特点:通过对视图的操作,会影响到原表数据。)

面向视图查询
select * from dept2_view;
面向视图插入
insert into dept2_view(deptno,dname,loc) values(60,'SALES','BEIJING');
查询原表数据
select * from dept2;
面向视图删除
delete from dept2_view;
面向视图更新
update emp_dept_view set sal = 1000 where dname = 'ACCOUNTING';
视图对象在实际开发到底有什么用?
create view
	emp_dept_view
as							# as后面只能是查询语句
	select
		e.ename,e.sal,d.dname
	from
		emp e
	join
		dept d
	on
		e.deptno = d.deptno;

假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?

在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。并且利于后期维护,因为修改的时候也只需要修改一个文件的位置就行,只需要修改视图对象所映射的SQL语句

DBA常用命令

导出(在doc命令下使用)
mysqldump 需要导出的数据库名称>导出的路径名称 用户	密码
mysqldump bjpowernode>D:\\bjpowernode.sql -uroot -p123456
删除数据库
drop database bjpowernode;
导入数据库(登录数据库后使用)
source 需要导入的文件的路径名称

数据库设计三范式

什么是数据库设计范式

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

第二范式:奖励在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖

第三范式:建立在第二范式的基础之上,要求所有主键字段字节依赖主键,

设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费

第一范式

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

必须有主键,并且每一个字段都是原子性不可再分。

[外链图片转存中…(img-z0wFq0hs-1666069104436)]

第二范式

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

背口诀:

​ 多对多怎么设计?

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

第三范式

第三范式建立在第二范式的基础之上

要求所有非主键字典必须字节依赖主键,不要产生传递依赖。

总结表的设计

一对多:

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

多对多:

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

一对一:

​ 一对一放到 一张表就行了

嘱咐一句话

数据库设计三范式是理论上的 。

实践和理论有的时候有偏差

最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。

因为在SQL当中,表和表之间连接 次数越多,效率越低(笛卡尔积)

有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的。

面试的时候把这句话说上:他就不会认为你是初级程序员了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值