MySQL用户名root,密码123456
此笔记只为了自学复习,同时也为能够帮助同样努力奋斗的小伙伴们。
该笔记是根据B站动力节点杜老师讲解的老杜带你学_mysql入门基础(mysql基础视频+数据库实战)写的,如果觉得侵权请联系我。同时很感谢动力节点以及杜老师,受益颇多。
net stop 服务名称;(net stop MySQL;)
net start 服务名称;(net start MySQL;)
show databases;
use test;
show tables;
DQL:
数据查询语言
select...
DML:
数据操作语言,对表中数据进行操作
insert 增
delete 删
update 改
DDL:
数据定义语言,对表结构进行操作
create:新建
drop:删除
alter:修改
TCL:
事务控制语言
commit:事务提交
rollback:事务回滚
DCL:
数据控制语言
grant:授权
revoke:撤销权限
...
.sql
文件source + 绝对路径
,回车
show tables;
select * from emp;
desc 表名;
或者
describe 表名;
select version();
\c -- 不执行之前的sql命令
或者
; -- 执行之前sql命令,如果sql有错,会报错
exit;
is null;
不能使用 != null;
在同时使用的时候根据需求判断是否需要添加括号
-- 下划线‘_’表示单个字母,‘%’一般用于模糊查询
select ename from emp where ename like '_A%';
注意:在sql中使用下划线没有特殊含义时,需要转义 ,前面加\
,如:'\_'
count 计数
sum 求和
avg 平均值
max 最大值
min 最小值
注意:分组函数会自动忽略null
count(*) 是统计总行数
count(具体字段) 会自动忽略null
分组函数不能用在where子句当中,如果没有分组(group by),整张表默认为一组。
select ...
from ...
where ...
group by ...
order by ...
为什么where后面不能用使用分组函数
答:分组函数需要在分组后才可以使用,而where在group by之前执行,所以where中不能含有分组函数,但是select里可以使用分组函数,原因是select中的字段是在group by之后执行的。
select ...
from ...
where ...
group by ...
having ...
order by ...
limit ...;
顺序:from -> where -> group by -> having -> select -> order by --> limit
distinct
:只能出现在所有字段的最前方
但是可以count(distinct job)
使用
内连接:
等值连接
非等值连接
自连接
外连接:
左连接 left outer join
右连接 right
全连接
避免笛卡尔积,需要连接时添加条件。
通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表的连接次数。
select
(select ...)
from
(select ...)
where
(select ...)
union
:效率要高一些,对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的翻;
但是union
可以减少匹配的次数,在减少匹配次数的情况下,还可以完成两个结果集的拼接。
举例:a 连接 b 连接 c
a:10条记录
b: 10条记录
c: 10条记录
表连接查询的匹配次数:10x10x10 = 1000次
使用union结果集合并的匹配次数:(1)a连接b一个结果:10 * 10 --> 100次
(2)a连接c一个结果: 10 * 10 --> 100次
所以使用union合并结果集的匹配次数是 100 + 100 = 200次
注意:在MySQL数据库中union
要求两个结果集合并时列数相同;
在oracle数据库中union
要求两个结果集合并时列数相同,而且要求合并时列与列的数据类型要一致
limit startIndex,length -- startIndex:起始下标,从0开始,length:长度
-- 举例:取出工资排名在[5-9]名的员工
limit 4,5; -- 这里的4是从0开始算,下标4代表的是第5名,这里的5代表的是[5-9]名员工的长度为9-5+1=5
limit 5 -- 缺省用法:取前5
-- 分页:每页显示pageSize条记录
-- 第pageNo页应该表示为:
limit (pageNo-1) * pageSize, pageSize
drop table 表名 if exists; -- 如果存在,再删除,避免表不存在执行删除操作而报错
str_to_date:将字符串varchar类型转换为date类型
date_format:将date类型转换成具有一定格式的varchar字符
点击这里跳转
insert into t_user(字段名1,字段名2) values(xx,xx),(xx,xx),(xx,xx),(xx,xx);
create table emp2 as select * from emp;
原理:将一个SQL查询结果当做一张表新建,可以完成表的快速复制,
表创建出来,同时表中的数据也就存在了。
delete from 表名;
delete原理:删除数据可以恢复,存储空间并没有释放
truncate table 表名;
truncate
快速删除表,效率比delete高,但是数据不可以回滚(这种操作属于DDL操作)
drop table 表名;
删除表
constraint(约束):在创建表的时候,可以给表中的字段加上一些约束,保证表的完整性、有效性!
非空约束:not null
唯一性约束: unique: unique(字段1,字段2),字段1和字段2联合起来唯一!
主键约束:primary key(简称PK)
外键约束:foreign key(简称FK):foreign key(字段a) references 表(字段b);外键可以为null,被引用字段不一定是主键,字段只要具备唯一性就可以了,不可以重复
检查约束:checke (mysql不支持,oracle支持)
约束直接添加到列的后面,叫做列级约束
约束没有添加到列的后面,而是单独写,这种约束称为表级约束(多个字段联合起来的约束只能是表级约束)
在mysql数据库中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段
在oracle数据库中不会
事务(transaction)是怎么做到多条DML语句同时成功或者同时失败的呢?
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件
事务开启了:
insert…
insert…
update…
insert…
事务结束了!
在事务的执行过程中,每一条DML的操作都会记录到“事务性活动的日志文件”中。
在事务的执行过程中,我们可以提交事务,也可以回滚事务。
提交事务(commit):清空事务性日志文件,将数据全部彻底持久化到数据库表中。
提交事务标志着,事务的结束。并且是一种全部成功的结束。
回滚事务(rollback):将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件。
回滚事务标志着,事务的结束。并且是一种全部失败的结束。
mysql默认事务自动提交(每执行一条DML语句,就提交一次),提交后无法rollbock
因此,自动提交实际上不符合我们的开发习惯,因为一个业务通常需要是多条DML语句共同执行才能完成,为了保证数据的安全,必须要求同时成功之后再提交,所以不能执行一条就提交一条
-- 将mysql的自动提交机制关闭
start transaction;
A:原子性
事务是最小的工作单元,不可在分
C:一致性
所有事务要求,在同一个事务中,所有的操作必须同时成功,或者同时失败,以保证数据的一致性
I:隔离性
A事务和B事务之间具有一定的隔离
D:持久性
事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上!
read uncommitted(读未提交)
read committed(读已提交)
repeatable read(可重复读)
serializable(可序列化)
-- 查看事务的隔离级别
select @@tx_isolation;
-- 设置全局事务的隔离级别
set global transaction isolation level read uncommitted;
MySQL的默认隔离级别是Repeatable Rad(可重复度),Oracle默认Read committed(读已提交),最高级别Serializable(可序列化)
索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。
一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。
索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
MySQL在查询的时候有两种方式:
第一种:全表扫描
第二种:根据索引检索。先通过索引定位一个大概的位置,然后直接定位到这个位置,做局域性扫描,缩小扫描的范围,快速的查找。这种查找方式属于通过索引检索,效率较高。
注意:在实际中,汉语字典的目录是排序的,按照a b c d e f … 排序。
为什么排序呢?因为只有排序了才会有区间查找这一说!(缩小扫描范围其实就是扫描某个区间罢了)
在mysql数据库中索引是需要排序的,并且这个索引的排序和TreeSet(TreeMap)数据结构相同。
TreeSet(TreeMap)底层是一个自平衡的二叉树!
在mysql中索引是一个B-Tree数据结构。
自平衡二叉树:遵循左小右大原则存放。采用中序遍历方式遍历取数据
- 在任何数据库中主键上都会自动添加索引对象,id字段上自动有索引,因为id是PK(primary key)。另外在mysql数据库中,一个字段上如果有unique约束的话,也会自动创建索引对象。
- 在任何数据库中,任何一张表的任何一条记录在硬盘存储上都有一个硬盘物理存储编号。
- 在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在
MyISAM存储引擎
中,索引存储在一个.MYI
文件中。在InnoDB存储引擎
中,索引存储在一个逻辑名称叫做tablespace
的当中。在MEMORY存储引擎
中索引被存储在内存
中。不管索引存储在哪里,索引在mysql当中都是一个树的形式存在。(自平衡二叉树:B-Tree)
在mysql中,主键上,以及unique(唯一约束)字段上都会自动添加索引的!
条件1:数据量庞大
条件2:该字段经常出现在where
后面,以条件的形式存在,也就是说这个字段总是被扫描
条件3:该字段很少的DML(insert delete update)操作。(因为DML之后,索引需要重新排序)
建议:
(1)不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。
(2)通过主键查询
(3)通过unique(唯一约束)字段进行查询
-- 创建索引
create index 索引名 on 表(字段);
-- 例子:给emp表上的ename字段添加索引,起名:emp_ename_index
create index emp_ename_index on emp(ename);
-- 删除索引
drop index 索引名 on 表;
-- 例子:将emp表上的emp_ename_index索引对象删除
drop index emp_ename_index on emp;
使用explain
关键字
从type类型可以直接看出,或者从执行的rows也可以看出
只列出常见的五种索引失效的情况
第一种:以%
开头模糊查询某个字段的值时,即使这个字段添加了索引,也不会走索引。所以开发中模糊查询尽量避免以%
开头。
select * from emp where ename like '%T';
第二种:使用or
时,如果使用or
那么要求or
两边的条件字段都要有索引,才会走索引,如果其中一边有一个字段没有索引,那么另一个字段上的索引也会失效。所以开发中不建议使用or
。
select * from emp where ename = 'KING' or job = 'MANAGER';
第三种:使用复合索引时,没有使用左侧的列查找,索引失效。
复合索引:两个或者多个字段联合起来添加一个索引,叫做复合索引
-- 创建复合索引
create index emp_job_sal_index on emp(job,sal);
-- 可以使用索引
select * from emp where job = 'MANAGER';
-- 索引失效
explain select * from emp where sal = 800;
第四种:在where
中索引列参加了运算,索引失效。
-- 创建索引
create index emp_sal_index on emp(sal);
-- 可以使用索引
select * from emp where sal = 800;
select * from emp where sal = 800 + 1;
-- 索引失效
select * from emp where sal+1 = 800;
第五种:在where
中索引列使用了函数
select * from emp where lower(ename) = 'smith';
优化的时候优先考虑的因素就是索引。
索引在数据库中分了很多类?
unique
(唯一性)约束的字段上添加索引注意:唯一性比较弱的字段上添加索引用处不大
view:站在不同的角度去看待同一份数据。
-- 表的快速复制
create table 新创建的表名 as select * from 已存在的表名;
-- 创建视图
create view 视图名称 as select * from 已存在的表名;
-- 删除视图
drop view 视图名称;
注意:只有DQL语句才能以view的形式创建。
create view view_name as 这里的语句必须是DQL语句;
面向视图对象进行增删改查,对视图对象的增删改查,会导致原表被操作!
视图的特点:通过对视图的操作,会影响到原表数据。
-- 面向视图查询
select * from 视图名;
-- 面向视图插入
insert into 视图名(字段1,字段2,字段3) values(xx,xx,xxx);
-- 面向视图删除
delete from 视图名;
-- 面向视图更新
update 视图名 set 视图中字段1 = xxx where 视图中字段2 = 'xxx';
-- 例子:
update emp_dept_view set sal = 1000 where dname = 'ACCOUNTING';
方便,简化开发,利于维护
当一条非常复杂的SQL需要被反复使用的时候,可以创建为视图,以后开发时只需面向视图开发,就像使用table(表)一样,可以对视图进行crud操作,同时对应的原表中的数据也会被改变。
视图不是在内存中,视图对象也是存储在硬盘上的,不会消失。
视图对应的语句只能是DQL语句。但是视图创建完成后可以对视图进行crud操作。
crud:
重点:
数据的导入和导出(数据备份)
其他命令了解一下即可。
-- 数据导出
-- 在windows的dos命令窗口中:
mysqldump 数据库名 > 导出的路径 -uroot -p123456
-- 例子
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123456
-- 数据导入
-- 先登录到mysql数据库服务器上,然后创建一个空的数据库
create database 数据库名称;
-- 使用数据库
use 数据库名称;
-- 导入数据
source .sql文件所在路径
source D:\bjpowernode.sql
数据库表设计的依据。教你怎么进行数据库表的设计。
第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分
第二范式:在第一范式的基础上,要求所有非主键字段完全依赖主键,不产生部分依赖。
第三范式:在第二范式的基础上,要求所有非主键字段直接依赖主键,不产生传递依赖。
设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。
最核心,最重要的范式,所有表设计必须满足。
表必须有主键,并且每一个字段都是原子性不可再分。
举例:一张没有主键的表中的一列字段为 联系方式: [email protected],1359999999
按照第一范式拆分为邮箱地址和联系电话,且必须要有主键
学生编号 学生姓名 联系方式
---------------------------------------------
1001 张三 [email protected],1359999999
1002 李四 [email protected],13699999999
1001 王五 [email protected],13488888888
经过修改后,满足第一范式:
学生编号(pk) 学生姓名 邮箱地址 联系电话
--------------------------------------------------------
1001 张三 [email protected] 1359999999
1002 李四 [email protected] 13699999999
1003 王五 [email protected] 13488888888
在第一范式的基础上,要求所有非主键字段完全依赖主键,不产生部分依赖。
举例:一张表中表述了学生和老师的关系:(1个学生可能有多个老师,一个老师有多个学生)
表与表的关系为:多对多关系!
由于表不满足第一范式,可以将学生编号和教师编号修改为联合主键,复合主键(PK: 学生编号+教师编号)。修改后,满足了第一范式,但是不满足第二范式(原因:张三”依赖1001,“王老师”依赖001,显然产生了部分依赖),可以将表拆分为三张表:学生表、教师表、学生教师关系表
产生部分依赖有什么缺点:数据冗余。空间浪费。“张三”重复了,“王老师”重复了。
学生编号 学生姓名 教师编号 教师姓名
------------------------------------------
1001 张三 001 王老师
1002 李四 002 赵老师
1003 王五 001 王老师
1001 张三 002 赵老师
经过修改后,满足第一范式:
学生编号+教师编号(pk) 学生姓名 教师姓名
----------------------------------------------------
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
口诀:多对多,三张表,关系表两个外键!
在第二范式的基础上,要求所有非主键字段直接依赖主键,不产生传递依赖。
举例:一张班级和学生的关系表(一个班级有多个学生)
表与表的
关系为:一对多关系!
学生编号(PK) 学生姓名 班级编号 班级名称
--------------------------------------------------------
1001 张三 01 一年一班
1002 李四 02 一年二班
1003 王五 03 一年三班
1004 赵六 03 一年三班
以上表的设计是描述:班级和学生的关系。很显然是1对多关系!
一个教室中有多个学生。
分析以上表是否满足第一范式?
满足第一范式,有主键。
分析以上表是否满足第二范式?
满足第二范式,因为主键不是复合主键,没有产生部分依赖。主键是单一主键。
分析以上表是否满足第三范式?
第三范式要求:不要产生传递依赖!
一年一班依赖01,01依赖1001,产生了传递依赖。
不符合第三范式的要求。产生了数据的冗余。
班级表:一
班级编号(pk) 班级名称
---------------------------------
01 一年一班
02 一年二班
03 一年三班
学生表:多
学生编号(PK) 学生姓名 班级编号(fk)
-------------------------------------------
1001 张三 01
1002 李四 02
1003 王五 03
1004 赵六 03
口诀:一对多,两张表,多的表加外键!
一对多:两张表,多的表加外键!
多对多:三张表,关系表两个外键!
一对一:正常情况下一对一放到一张表就可以了,但是在实际开发中,一张表的字段太多,需要拆分表。
一对一怎么设计?
没有拆分表之前:一张表 t_user
id login_name login_pwd real_name email address ........
-----------------------------------------------------------------------------
1 zhangsan 123 张三 zhangsan@xxx ... ...
2 lisi 123 李四 lisi@xxx ... ...
这种庞大的表建议拆分为两张:t_login 登录信息表 和 t_user 用户详细信息表
t_login 登录信息表
id(pk) login_name login_pwd
---------------------------------
1 zhangsan 123
2 lisi 123
t_user 用户详细信息表
id(pk) real_name email address ...... login_id(fk+unique)
----------------------------------------------------------------------------------
100 张三 zhangsan@xxx ... ... 1
200 李四 lisi@xxx ... ... 2
口诀:一对一,外键唯一,不可重复!
数据库设计三范式是理论上的。
实践和理论有的时候有偏差。
最终的目的都是为了满足客户的需求,有时候会拿冗余换执行速度。
因为在sql中,表和表之间连接次数越多,笛卡尔积越容易大,那样效率越低。
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的,并且对于开发人员来说,sql语句的编写难度也会降低。
再次练习一遍,多写多练方可熟练掌握。点击这里跳转